mirror of
https://github.com/UnickSoft/graphonline.git
synced 2025-07-01 15:26:12 +00:00
Change script location.
Split js code. Added cache and changed loading mechanism for js sources.
This commit is contained in:
parent
c29ad15e3c
commit
43a4b44a22
@ -173,11 +173,15 @@
|
||||
return SITE_ROOT . "{$dir}{$uri}";
|
||||
}
|
||||
|
||||
function RootCacheJS($uri = '', $version = '') {
|
||||
function RootCacheJS($uri = '') {
|
||||
global $g_config;
|
||||
|
||||
return Root(($g_config['use_js_cache'] ? $uri . ".cache" :
|
||||
$uri) . "?v=" . $version);
|
||||
$cacheFilePath = Root($uri . ".cache");
|
||||
$filePath = Root($uri);
|
||||
$cacheExists = file_exists("." . $cacheFilePath);
|
||||
$finalFileName = $cacheExists && $g_config['use_js_cache'] ? $cacheFilePath : $filePath;
|
||||
|
||||
return $finalFileName . "?v=" . $g_config['engine_version'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -145,6 +145,8 @@
|
||||
|
||||
$g_lang["opensource_message"] = "Our project is now open source. More details...";
|
||||
|
||||
$g_lang["we_are_improving"] = "We are improving Graphonline, if you faced with any problem please let us know: admin@graphonline.ru";
|
||||
|
||||
$g_lang["settings"] = "Settings";
|
||||
$g_lang["common_vertex_settings"] = "Common vertices";
|
||||
$g_lang["selected_vertex_settings"] = "Selected vertices";
|
||||
|
@ -148,6 +148,8 @@
|
||||
|
||||
$g_lang["opensource_message"] = "Наш проект стал проектом с открытым исходным кодом. Подробнее...";
|
||||
|
||||
$g_lang["we_are_improving"] = "Мы улучшаем Graphonline, если вы столкнулись с проблемами напишете нам: admin@graphonline.ru";
|
||||
|
||||
$g_lang["settings"] = "Настройки";
|
||||
$g_lang["common_vertex_settings"] = "Обычных вершин";
|
||||
$g_lang["selected_vertex_settings"] = "Выделенных вершин";
|
||||
|
File diff suppressed because it is too large
Load Diff
9
script/entities/edge/api/index.js
Normal file
9
script/entities/edge/api/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
{
|
||||
let modulDir = "entities/edge/";
|
||||
|
||||
doInclude ([
|
||||
include ("model/BaseEdge.js", modulDir),
|
||||
include ("model/EdgeModel.js", modulDir)
|
||||
])
|
||||
}
|
0
script/BaseEdge.js → script/entities/edge/model/BaseEdge.js
Executable file → Normal file
0
script/BaseEdge.js → script/entities/edge/model/BaseEdge.js
Executable file → Normal file
2
script/EdgeModel.js → script/entities/edge/model/EdgeModel.js
Executable file → Normal file
2
script/EdgeModel.js → script/entities/edge/model/EdgeModel.js
Executable file → Normal file
@ -31,7 +31,7 @@ EdgeModel.prototype.SaveToXML = function ()
|
||||
{
|
||||
return "model_width=\"" + this.width + "\" " +
|
||||
"model_type=\"" + this.type + "\" " +
|
||||
"model_curveValue=\"" + this.curveValue + "\" "
|
||||
"model_curveValue=\"" + this.curveValue + "\" " +
|
||||
"model_default=\"" + this.default + "\" ";
|
||||
}
|
||||
|
11
script/entities/graph/api/index.js
Normal file
11
script/entities/graph/api/index.js
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
{
|
||||
let modulDir = "entities/graph/";
|
||||
|
||||
doInclude ([
|
||||
include ("shared/point.js"),
|
||||
include ("entities/edge/api/index.js"),
|
||||
include ("entities/vertex/api/index.js"),
|
||||
include ("model/Graph.js", modulDir)
|
||||
])
|
||||
}
|
8
script/entities/vertex/api/index.js
Normal file
8
script/entities/vertex/api/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
let modulDir = "entities/vertex/";
|
||||
|
||||
doInclude ([
|
||||
include ("model/BaseVertex.js", modulDir),
|
||||
include ("model/VertexModel.js", modulDir)
|
||||
])
|
||||
}
|
0
script/BaseVertex.js → script/entities/vertex/model/BaseVertex.js
Executable file → Normal file
0
script/BaseVertex.js → script/entities/vertex/model/BaseVertex.js
Executable file → Normal file
2
script/VertexModel.js → script/entities/vertex/model/VertexModel.js
Executable file → Normal file
2
script/VertexModel.js → script/entities/vertex/model/VertexModel.js
Executable file → Normal file
@ -3,7 +3,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
const defaultVertexDiameter = 30;
|
||||
const defaultVertexDiameter = 30;
|
||||
|
||||
function VertexModel()
|
||||
{
|
59
script/features/add_vertices_handler/index.js
Normal file
59
script/features/add_vertices_handler/index.js
Normal file
@ -0,0 +1,59 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Add Graph handler.
|
||||
*
|
||||
*/
|
||||
function AddGraphHandler(app)
|
||||
{
|
||||
this.removeStack = true;
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = g_clickToAddVertex;
|
||||
this.addContextMenu();
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
AddGraphHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
|
||||
AddGraphHandler.prototype.MouseDown = function(pos)
|
||||
{
|
||||
this.app.PushToStack("Add");
|
||||
|
||||
this.app.CreateNewGraph(pos.x, pos.y);
|
||||
this.needRedraw = true;
|
||||
this.inited = false;
|
||||
}
|
||||
|
||||
AddGraphHandler.prototype.InitControls = function()
|
||||
{
|
||||
var enumVertexsText = document.getElementById("enumVertexsText");
|
||||
if (enumVertexsText)
|
||||
{
|
||||
var enumsList = this.app.GetEnumVerticesList();
|
||||
for (var i = 0; i < enumsList.length; i ++)
|
||||
{
|
||||
var option = document.createElement('option');
|
||||
option.text = enumsList[i]["text"];
|
||||
option.value = enumsList[i]["value"];
|
||||
enumVertexsText.add(option, i);
|
||||
if (enumsList[i]["select"])
|
||||
{
|
||||
enumVertexsText.selectedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
var addGraphHandler = this;
|
||||
enumVertexsText.onchange = function () {
|
||||
addGraphHandler.ChangedType();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
AddGraphHandler.prototype.ChangedType = function()
|
||||
{
|
||||
var enumVertexsText = document.getElementById("enumVertexsText");
|
||||
|
||||
this.app.SetEnumVerticesType(enumVertexsText.options[enumVertexsText.selectedIndex].value);
|
||||
}
|
131
script/features/algorithm_handler/index.js
Normal file
131
script/features/algorithm_handler/index.js
Normal file
@ -0,0 +1,131 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Algorithm Graph handler.
|
||||
*
|
||||
*/
|
||||
function AlgorithmGraphHandler(app, algorithm)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.algorithm = algorithm;
|
||||
this.SaveUpText();
|
||||
|
||||
this.UpdateResultAndMessage();
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
AlgorithmGraphHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
|
||||
// Rest this handler.
|
||||
AlgorithmGraphHandler.prototype.MouseMove = function(pos) {}
|
||||
|
||||
AlgorithmGraphHandler.prototype.MouseDown = function(pos)
|
||||
{
|
||||
this.app.setRenderPath([]);
|
||||
|
||||
if (this.algorithm.instance())
|
||||
{
|
||||
this.app.SetDefaultHandler();
|
||||
}
|
||||
else
|
||||
{
|
||||
var selectedObject = this.GetSelectedGraph(pos);
|
||||
if (selectedObject && (selectedObject instanceof BaseVertex))
|
||||
{
|
||||
if (this.algorithm.selectVertex(selectedObject))
|
||||
{
|
||||
this.needRedraw = true;
|
||||
}
|
||||
|
||||
this.UpdateResultAndMessage();
|
||||
}
|
||||
else if (selectedObject && (selectedObject instanceof BaseEdge))
|
||||
{
|
||||
if (this.algorithm.selectEdge(selectedObject))
|
||||
{
|
||||
this.needRedraw = true;
|
||||
}
|
||||
|
||||
this.UpdateResultAndMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.algorithm.deselectAll())
|
||||
{
|
||||
this.needRedraw = true;
|
||||
this.UpdateResultAndMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlgorithmGraphHandler.prototype.MouseUp = function(pos) {}
|
||||
|
||||
AlgorithmGraphHandler.prototype.GetSelectedGroup = function(object)
|
||||
{
|
||||
return this.algorithm.getObjectSelectedGroup(object);
|
||||
}
|
||||
|
||||
AlgorithmGraphHandler.prototype.RestoreAll = function()
|
||||
{
|
||||
this.app.setRenderPath([]);
|
||||
|
||||
if (this.algorithm.needRestoreUpText())
|
||||
{
|
||||
this.RestoreUpText();
|
||||
}
|
||||
|
||||
if (this.algorithm.wantRestore())
|
||||
{
|
||||
this.algorithm.restore();
|
||||
}
|
||||
}
|
||||
|
||||
AlgorithmGraphHandler.prototype.SaveUpText = function()
|
||||
{
|
||||
this.vertexUpText = {};
|
||||
var graph = this.app.graph;
|
||||
for (i = 0; i < graph.vertices.length; i ++)
|
||||
{
|
||||
this.vertexUpText[graph.vertices[i].id] = graph.vertices[i].upText;
|
||||
}
|
||||
}
|
||||
|
||||
AlgorithmGraphHandler.prototype.RestoreUpText = function()
|
||||
{
|
||||
var graph = this.app.graph;
|
||||
|
||||
for (i = 0; i < graph.vertices.length; i ++)
|
||||
{
|
||||
if (graph.vertices[i].id in this.vertexUpText)
|
||||
{
|
||||
graph.vertices[i].upText = this.vertexUpText[graph.vertices[i].id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlgorithmGraphHandler.prototype.UpdateResultAndMessage = function()
|
||||
{
|
||||
var self = this;
|
||||
result = this.algorithm.result(function (result)
|
||||
{
|
||||
self.message = self.algorithm.getMessage(g_language);
|
||||
self.app.resultCallback(result);
|
||||
});
|
||||
|
||||
this.app.resultCallback(result);
|
||||
|
||||
this.message = this.algorithm.getMessage(g_language);
|
||||
}
|
||||
|
||||
AlgorithmGraphHandler.prototype.InitControls = function()
|
||||
{
|
||||
this.algorithm.messageWasChanged();
|
||||
}
|
||||
|
||||
AlgorithmGraphHandler.prototype.GetMessage = function()
|
||||
{
|
||||
return this.algorithm.getMessage(g_language);
|
||||
}
|
35
script/features/algorithms/api/index.js
Normal file
35
script/features/algorithms/api/index.js
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
let modulDir = "features/algorithms/";
|
||||
|
||||
doInclude ([
|
||||
include ("model/Algorithms.js", modulDir),
|
||||
include ("model/BaseTraversal.js", modulDir)
|
||||
])
|
||||
|
||||
function loadAsyncAlgorithms(onFinish) {
|
||||
let pluginsList = ["BFS.js",
|
||||
"Coloring.js",
|
||||
"ConnectedComponent.js",
|
||||
"DFS.js",
|
||||
"EulerianLoop.js",
|
||||
"EulerianPath.js",
|
||||
"FindAllPatches.js",
|
||||
"FindLongestPath.js",
|
||||
"FindShortPatchsFromOne.js",
|
||||
"Floid.js",
|
||||
"GraphReorder.js",
|
||||
"HamiltonianLoop.js",
|
||||
"HamiltonianPath.js",
|
||||
"IsomorphismCheck.js",
|
||||
"MaxClique.js",
|
||||
"MaxFlow.js",
|
||||
"MinimumSpanningTree.js",
|
||||
"ModernGraphStyle.js",
|
||||
"RadiusAndDiameter.js",
|
||||
"ShortestPath.js",
|
||||
"VerticesDegree.js"];
|
||||
|
||||
doIncludeAsync (pluginsList.map((plugin) => include ("model/plugins/" + plugin, modulDir)), onFinish);
|
||||
}
|
||||
|
||||
}
|
0
script/BaseTraversal.js → script/features/algorithms/model/BaseTraversal.js
Executable file → Normal file
0
script/BaseTraversal.js → script/features/algorithms/model/BaseTraversal.js
Executable file → Normal file
0
script/plugins/BFS.js → script/features/algorithms/model/plugins/BFS.js
Executable file → Normal file
0
script/plugins/BFS.js → script/features/algorithms/model/plugins/BFS.js
Executable file → Normal file
0
script/plugins/Coloring.js → script/features/algorithms/model/plugins/Coloring.js
Executable file → Normal file
0
script/plugins/Coloring.js → script/features/algorithms/model/plugins/Coloring.js
Executable file → Normal file
0
script/plugins/ConnectedComponent.js → script/features/algorithms/model/plugins/ConnectedComponent.js
Executable file → Normal file
0
script/plugins/ConnectedComponent.js → script/features/algorithms/model/plugins/ConnectedComponent.js
Executable file → Normal file
0
script/plugins/DFS.js → script/features/algorithms/model/plugins/DFS.js
Executable file → Normal file
0
script/plugins/DFS.js → script/features/algorithms/model/plugins/DFS.js
Executable file → Normal file
0
script/plugins/EulerianLoop.js → script/features/algorithms/model/plugins/EulerianLoop.js
Executable file → Normal file
0
script/plugins/EulerianLoop.js → script/features/algorithms/model/plugins/EulerianLoop.js
Executable file → Normal file
0
script/plugins/EulerianPath.js → script/features/algorithms/model/plugins/EulerianPath.js
Executable file → Normal file
0
script/plugins/EulerianPath.js → script/features/algorithms/model/plugins/EulerianPath.js
Executable file → Normal file
0
script/plugins/Floid.js → script/features/algorithms/model/plugins/Floid.js
Executable file → Normal file
0
script/plugins/Floid.js → script/features/algorithms/model/plugins/Floid.js
Executable file → Normal file
0
script/plugins/GraphReorder.js → script/features/algorithms/model/plugins/GraphReorder.js
Executable file → Normal file
0
script/plugins/GraphReorder.js → script/features/algorithms/model/plugins/GraphReorder.js
Executable file → Normal file
0
script/plugins/HamiltonianLoop.js → script/features/algorithms/model/plugins/HamiltonianLoop.js
Executable file → Normal file
0
script/plugins/HamiltonianLoop.js → script/features/algorithms/model/plugins/HamiltonianLoop.js
Executable file → Normal file
0
script/plugins/HamiltonianPath.js → script/features/algorithms/model/plugins/HamiltonianPath.js
Executable file → Normal file
0
script/plugins/HamiltonianPath.js → script/features/algorithms/model/plugins/HamiltonianPath.js
Executable file → Normal file
0
script/plugins/MaxFlow.js → script/features/algorithms/model/plugins/MaxFlow.js
Executable file → Normal file
0
script/plugins/MaxFlow.js → script/features/algorithms/model/plugins/MaxFlow.js
Executable file → Normal file
0
script/plugins/MinimumSpanningTree.js → script/features/algorithms/model/plugins/MinimumSpanningTree.js
Executable file → Normal file
0
script/plugins/MinimumSpanningTree.js → script/features/algorithms/model/plugins/MinimumSpanningTree.js
Executable file → Normal file
0
script/plugins/ModernGraphStyle.js → script/features/algorithms/model/plugins/ModernGraphStyle.js
Executable file → Normal file
0
script/plugins/ModernGraphStyle.js → script/features/algorithms/model/plugins/ModernGraphStyle.js
Executable file → Normal file
0
script/plugins/RadiusAndDiameter.js → script/features/algorithms/model/plugins/RadiusAndDiameter.js
Executable file → Normal file
0
script/plugins/RadiusAndDiameter.js → script/features/algorithms/model/plugins/RadiusAndDiameter.js
Executable file → Normal file
0
script/plugins/ShortestPath.js → script/features/algorithms/model/plugins/ShortestPath.js
Executable file → Normal file
0
script/plugins/ShortestPath.js → script/features/algorithms/model/plugins/ShortestPath.js
Executable file → Normal file
0
script/plugins/VerticesDegree.js → script/features/algorithms/model/plugins/VerticesDegree.js
Executable file → Normal file
0
script/plugins/VerticesDegree.js → script/features/algorithms/model/plugins/VerticesDegree.js
Executable file → Normal file
457
script/features/base_handler/index.js
Normal file
457
script/features/base_handler/index.js
Normal file
@ -0,0 +1,457 @@
|
||||
/**
|
||||
* Base Handler.
|
||||
*
|
||||
*/
|
||||
function BaseHandler(app)
|
||||
{
|
||||
this.app = app;
|
||||
this.app.setRenderPath([]);
|
||||
|
||||
if (this.removeStack) {
|
||||
this.removeContextMenu();
|
||||
}
|
||||
this.contextMenuObject = null;
|
||||
this.contextMenuPoint = null;
|
||||
//this.app.ClearUndoStack();
|
||||
}
|
||||
|
||||
// Need redraw or nor.
|
||||
BaseHandler.prototype.needRedraw = false;
|
||||
BaseHandler.prototype.objects = [];
|
||||
BaseHandler.prototype.message = "";
|
||||
|
||||
|
||||
BaseHandler.prototype.IsNeedRedraw = function(object)
|
||||
{
|
||||
return this.needRedraw;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.RestRedraw = function(object)
|
||||
{
|
||||
this.needRedraw = false;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.SetObjects = function(objects)
|
||||
{
|
||||
this.objects = objects;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.GetSelectedGraph = function(pos)
|
||||
{
|
||||
// Selected Graph.
|
||||
var res = null;
|
||||
for (var i = 0; i < this.app.graph.vertices.length; i ++)
|
||||
{
|
||||
if (this.app.graph.vertices[i].HitTest(pos))
|
||||
{
|
||||
// Select last of them.
|
||||
res = this.app.graph.vertices[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.GetSelectedArc = function(pos)
|
||||
{
|
||||
// Selected Arc.
|
||||
for (var i = 0; i < this.app.graph.edges.length; i ++)
|
||||
{
|
||||
var edge = this.app.graph.edges[i];
|
||||
|
||||
if (edge.HitTest(new Point(pos.x, pos.y)))
|
||||
return edge;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.GetSelectedObject = function(pos)
|
||||
{
|
||||
var graphObject = this.GetSelectedGraph(pos);
|
||||
if (graphObject)
|
||||
{
|
||||
return graphObject;
|
||||
}
|
||||
|
||||
var arcObject = this.GetSelectedArc(pos);
|
||||
if (arcObject)
|
||||
{
|
||||
return arcObject;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
BaseHandler.prototype.GetUpText = function(object)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
BaseHandler.prototype.GetMessage = function()
|
||||
{
|
||||
return this.message;
|
||||
}
|
||||
|
||||
|
||||
BaseHandler.prototype.MouseMove = function(pos) {}
|
||||
|
||||
BaseHandler.prototype.MouseDown = function(pos) {}
|
||||
|
||||
BaseHandler.prototype.MouseUp = function(pos) {}
|
||||
|
||||
BaseHandler.prototype.GetSelectedGroup = function(object)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.InitControls = function()
|
||||
{
|
||||
var vertex1Text = document.getElementById("Vertex1");
|
||||
if (vertex1Text)
|
||||
{
|
||||
var handler = this;
|
||||
vertex1Text.onchange = function () {
|
||||
for (var i = 0; i < handler.app.graph.vertices.length; i++)
|
||||
{
|
||||
if (handler.app.graph.vertices[i].mainText == vertex1Text.value)
|
||||
{
|
||||
handler.SelectFirstVertexMenu(vertex1Text, handler.app.graph.vertices[i]);
|
||||
userAction("selectVertex1_menu");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.UpdateFirstVertexMenu(vertex1Text);
|
||||
}
|
||||
|
||||
var vertex2Text = document.getElementById("Vertex2");
|
||||
if (vertex2Text)
|
||||
{
|
||||
var handler = this;
|
||||
vertex2Text.onchange = function () {
|
||||
for (var i = 0; i < handler.app.graph.vertices.length; i++)
|
||||
{
|
||||
if (handler.app.graph.vertices[i].mainText == vertex2Text.value)
|
||||
{
|
||||
handler.SelectSecondVertexMenu(vertex2Text, handler.app.graph.vertices[i]);
|
||||
userAction("selectVertex2_menu");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.UpdateSecondVertexMenu(vertex2Text);
|
||||
}
|
||||
}
|
||||
|
||||
BaseHandler.prototype.GetNodesPath = function(array, start, count)
|
||||
{
|
||||
var res = [];
|
||||
for (var index = start; index < start + count; index++)
|
||||
{
|
||||
res.push(this.app.graph.FindVertex(array[index].value));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.RestoreAll = function()
|
||||
{
|
||||
}
|
||||
|
||||
BaseHandler.prototype.GetSelectVertexMenu = function(menuName)
|
||||
{
|
||||
var res = "<input list=\"vertexList" + menuName + "\" id=\"" + menuName + "\" class=\"SelectVertexInput\"/>" +
|
||||
"<datalist id=\"vertexList" + menuName + "\">";
|
||||
|
||||
for (var i = 0; i < this.app.graph.vertices.length; i++)
|
||||
{
|
||||
res = res + "<option value=\"" + this.app.graph.vertices[i].mainText + "\"/>";
|
||||
}
|
||||
|
||||
return res + "</datalist>";
|
||||
}
|
||||
|
||||
BaseHandler.prototype.GetSelect2VertexMenu = function()
|
||||
{
|
||||
return "<span style=\"float:right\">" +
|
||||
this.GetSelectVertexMenu("Vertex1") + " → " + this.GetSelectVertexMenu("Vertex2") + "</span>";
|
||||
}
|
||||
|
||||
BaseHandler.prototype.SelectFirstVertexMenu = function(vertex1Text, vertex)
|
||||
{}
|
||||
|
||||
BaseHandler.prototype.UpdateFirstVertexMenu = function()
|
||||
{}
|
||||
|
||||
BaseHandler.prototype.SelectSecondVertexMenu = function(vertex2Text, vertex)
|
||||
{}
|
||||
|
||||
BaseHandler.prototype.UpdateSecondVertexMenu = function()
|
||||
{}
|
||||
|
||||
BaseHandler.prototype.GetSelectedVertex = function()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
BaseHandler.prototype.addContextMenu = function()
|
||||
{
|
||||
var $contextMenu = $("#contextMenu");
|
||||
|
||||
var handler = this;
|
||||
|
||||
$("#Context_Delete").click(function() {
|
||||
if (handler.contextMenuObject != null) {
|
||||
handler.app.PushToStack("DeleteObject");
|
||||
handler.app.DeleteObject(handler.contextMenuObject);
|
||||
handler.app.redrawGraph();
|
||||
userAction("DeleteObject_contextMenu");
|
||||
}
|
||||
});
|
||||
|
||||
$("#Context_Rename").click(function() {
|
||||
if (handler.contextMenuObject != null) {
|
||||
var callback = function (enumType) {
|
||||
handler.RenameVertex(enumType.GetVertexText(0), handler.contextMenuObject);
|
||||
userAction("RenameVertex_contextMenu");
|
||||
};
|
||||
var customEnum = new TextEnumVerticesCustom(handler.app);
|
||||
customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.contextMenuObject.mainText);
|
||||
}
|
||||
});
|
||||
|
||||
$("#Context_Connect").click(function() {
|
||||
if (handler.contextMenuObject != null && handler.GetSelectedVertex() != null) {
|
||||
var addFunc = function(firstVertex, secondVertex, direct) {
|
||||
handler.app.CreateNewArc(firstVertex, secondVertex, direct,
|
||||
document.getElementById('EdgeWeight').value,
|
||||
$("#RadiosReplaceEdge").prop("checked"),
|
||||
document.getElementById('EdgeLable').value);
|
||||
handler.app.redrawGraph();
|
||||
}
|
||||
handler.ShowCreateEdgeDialog(handler.GetSelectedVertex(), handler.contextMenuObject, addFunc);
|
||||
}
|
||||
});
|
||||
|
||||
$("#Context_Delete_Edge").click(function() {
|
||||
if (handler.contextMenuObject != null) {
|
||||
handler.app.PushToStack("DeleteObject");
|
||||
handler.app.DeleteObject(handler.contextMenuObject);
|
||||
handler.app.redrawGraph();
|
||||
userAction("DeleteObject_contextMenu");
|
||||
}
|
||||
});
|
||||
|
||||
$("#Context_Edit_Edge").click(function() {
|
||||
if (handler.contextMenuObject != null) {
|
||||
handler.ShowEditEdgeDialog(handler.contextMenuObject);
|
||||
}
|
||||
});
|
||||
|
||||
$("#Context_Add_Vertex").click(function() {
|
||||
handler.app.PushToStack("Add");
|
||||
handler.app.CreateNewGraph(handler.contextMenuPoint.x, handler.contextMenuPoint.y);
|
||||
handler.app.redrawGraph();
|
||||
});
|
||||
|
||||
$("#Context_Back_Color").click(function() {
|
||||
var setupBackgroundStyle = new SetupBackgroundStyle(handler.app);
|
||||
setupBackgroundStyle.show();
|
||||
});
|
||||
|
||||
$("body").on("contextmenu", "canvas", function(e) {
|
||||
handler.contextMenuPoint = handler.app.getMousePos(handler.app.canvas, e);
|
||||
handler.contextMenuObject = handler.GetSelectedObject(handler.contextMenuPoint);
|
||||
if (handler.contextMenuObject instanceof BaseVertex) {
|
||||
$("#edgeContextMenu").hide();
|
||||
$("#backgroundContextMenu").hide();
|
||||
$("#vertexContextMenu").show();
|
||||
if (handler.GetSelectedVertex() == null) {
|
||||
$("#Context_Connect").hide();
|
||||
} else {
|
||||
$("#Context_Connect").show();
|
||||
}
|
||||
} else if (handler.contextMenuObject instanceof BaseEdge) {
|
||||
$("#vertexContextMenu").hide();
|
||||
$("#backgroundContextMenu").hide();
|
||||
$("#edgeContextMenu").show();
|
||||
} else {
|
||||
$("#vertexContextMenu").hide();
|
||||
$("#edgeContextMenu").hide();
|
||||
$("#backgroundContextMenu").show();
|
||||
}
|
||||
|
||||
$contextMenu.css({
|
||||
display: "block",
|
||||
left: e.offsetX,
|
||||
top: e.offsetY
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$("body").click(function() {
|
||||
$contextMenu.hide();
|
||||
});
|
||||
}
|
||||
|
||||
BaseHandler.prototype.removeContextMenu = function()
|
||||
{
|
||||
$("body").off("contextmenu");
|
||||
$("#Context_Delete").off("click");
|
||||
$("#Context_Rename").off("click");
|
||||
$("#Context_Connect").off("click");
|
||||
$("#Context_Delete_Edge").off("click");
|
||||
$("#Context_Edit_Edge").off("click");
|
||||
$("#Context_Add_Vertex").off("click");
|
||||
$("#Context_Back_Color").off("click");
|
||||
}
|
||||
|
||||
BaseHandler.prototype.RenameVertex = function(text, object)
|
||||
{
|
||||
if (object != null && (object instanceof BaseVertex))
|
||||
{
|
||||
this.app.PushToStack("RenameVertex");
|
||||
object.mainText = text;
|
||||
this.app.redrawGraph();
|
||||
}
|
||||
}
|
||||
|
||||
BaseHandler.prototype.ShowCreateEdgeDialog = function(firstVertex, secondVertex, addEdgeCallBack) {
|
||||
if (!this.app.graph.isMulti())
|
||||
{
|
||||
var hasEdge = this.app.graph.FindEdgeAny(firstVertex.id, secondVertex.id);
|
||||
var hasReverseEdge = this.app.graph.FindEdgeAny(secondVertex.id, firstVertex.id);
|
||||
|
||||
if (hasEdge == null && hasReverseEdge == null)
|
||||
{
|
||||
$("#RadiosReplaceEdge").prop("checked", true);
|
||||
$("#NewEdgeAction" ).hide();
|
||||
}
|
||||
else {
|
||||
$( "#NewEdgeAction" ).show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#RadiosAddEdge").prop("checked", true);
|
||||
$("#NewEdgeAction" ).hide();
|
||||
}
|
||||
|
||||
var dialogButtons = {};
|
||||
var handler = this;
|
||||
|
||||
$("#CheckSaveDefaultEdge").prop("checked", false);
|
||||
$("#defaultEdgeDialogBlock").show();
|
||||
|
||||
dialogButtons[g_orintEdge] = function() {
|
||||
handler.app.PushToStack("Connect");
|
||||
addEdgeCallBack(firstVertex, secondVertex, true);
|
||||
//handler.AddNewEdge(selectedObject, true);
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
dialogButtons[g_notOrintEdge] = function() {
|
||||
handler.app.PushToStack("Connect");
|
||||
addEdgeCallBack(firstVertex, secondVertex, false);
|
||||
//handler.AddNewEdge(selectedObject, false);
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
var edgePresets = this.app.GetEdgePresets();
|
||||
var presetsStr = "<span onClick=\"document.getElementById('EdgeWeight').value='" + g_DefaultWeightPreset
|
||||
+ "'; document.getElementById('EdgeWeightSlider').value='" + g_DefaultWeightPreset
|
||||
+ "';\" style=\"cursor: pointer\" class=\"defaultWeigth\">" + g_DefaultWeightPreset + "</span>";
|
||||
|
||||
for(var i = 0; i < edgePresets.length; i ++)
|
||||
{
|
||||
var edgePreset = edgePresets[i];
|
||||
presetsStr += "<span onClick=\"document.getElementById('EdgeWeight').value='" + edgePreset
|
||||
+ "'; document.getElementById('EdgeWeightSlider').value=" + edgePreset
|
||||
+ ";\" style=\"cursor: pointer\" class=\"defaultWeigth\">" + edgePreset + "</span>";
|
||||
}
|
||||
document.getElementById("EdgesPresets").innerHTML = presetsStr;
|
||||
document.getElementById('EdgeLable').value = "";
|
||||
|
||||
$( "#addEdge" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_addEdge,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog',
|
||||
open: function () {
|
||||
$(this).off('submit').on('submit', function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
// Focues weight
|
||||
setTimeout(function(){
|
||||
const weightInput = document.getElementById('EdgeWeight');
|
||||
if(weightInput)
|
||||
{
|
||||
weightInput.focus();
|
||||
weightInput.select();
|
||||
}
|
||||
},0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
BaseHandler.prototype.ShowEditEdgeDialog = function(edgeObject) {
|
||||
var dialogButtons = {};
|
||||
|
||||
var handler = this;
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
handler.app.PushToStack("ChangeEdge");
|
||||
|
||||
edgeObject.SetWeight(document.getElementById('EdgeWeight').value);
|
||||
edgeObject.SetUpText(document.getElementById('EdgeLable').value);
|
||||
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
|
||||
userAction("ChangeWeight");
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
document.getElementById('EdgeWeight').value = edgeObject.useWeight ? edgeObject.weight : g_noWeight;
|
||||
document.getElementById('EdgeWeightSlider').value = edgeObject.useWeight ? edgeObject.weight : 0;
|
||||
|
||||
var edgePresets = handler.app.GetEdgePresets();
|
||||
var presetsStr = "<span onClick=\"document.getElementById('EdgeWeight').value='" + g_DefaultWeightPreset + "'; document.getElementById('EdgeWeightSlider').value='" +
|
||||
g_DefaultWeightPreset + "';\" style=\"cursor: pointer\" class=\"defaultWeigth\">" + g_DefaultWeightPreset + "</span>";
|
||||
|
||||
for(var i = 0; i < edgePresets.length; i ++)
|
||||
{
|
||||
var edgePreset = edgePresets[i];
|
||||
presetsStr += "<span onClick=\"document.getElementById('EdgeWeight').value='" + edgePreset + "'; document.getElementById('EdgeWeightSlider').value=" +
|
||||
edgePreset + ";\" style=\"cursor: pointer\" class=\"defaultWeigth\">" + edgePreset + "</span>";
|
||||
}
|
||||
document.getElementById("EdgesPresets").innerHTML = presetsStr;
|
||||
document.getElementById('EdgeLable').value = edgeObject.upText;
|
||||
|
||||
$("#CheckSaveDefaultEdge").prop("checked", false);
|
||||
|
||||
$("#defaultEdgeDialogBlock").hide();
|
||||
|
||||
$( "#addEdge" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_editWeight,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog',
|
||||
open: function () {
|
||||
$(handler).off('submit').on('submit', function () {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
226
script/features/connect_vertices_handler/index.js
Normal file
226
script/features/connect_vertices_handler/index.js
Normal file
@ -0,0 +1,226 @@
|
||||
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Connection Graph handler.
|
||||
*
|
||||
*/
|
||||
function ConnectionGraphHandler(app)
|
||||
{
|
||||
this.removeStack = true;
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.SelectFirst();
|
||||
this.addContextMenu();
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
ConnectionGraphHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
// First selected.
|
||||
ConnectionGraphHandler.prototype.firstObject = null;
|
||||
|
||||
ConnectionGraphHandler.prototype.GetSelectedVertex = function()
|
||||
{
|
||||
return (this.firstObject instanceof BaseVertex) ? this.firstObject : null;
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.AddNewEdge = function(selectedObject, isDirect)
|
||||
{
|
||||
let newEdge = this.app.CreateNewArc(this.firstObject, selectedObject, isDirect,
|
||||
document.getElementById('EdgeWeight').value,
|
||||
$("#RadiosReplaceEdge").prop("checked"),
|
||||
document.getElementById('EdgeLable').value);
|
||||
|
||||
if ($("#CheckSaveDefaultEdge").prop("checked")) {
|
||||
let defaultEdge = new BaseEdge();
|
||||
defaultEdge.copyFrom(this.app.graph.edges[newEdge]);
|
||||
this.app.setDefaultEdge(defaultEdge);
|
||||
}
|
||||
|
||||
this.SelectFirst();
|
||||
this.app.NeedRedraw();
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.AddDefaultEdge = function(selectedObject)
|
||||
{
|
||||
let defaultEdge = this.app.getDefaultEdge();
|
||||
let newEdge = this.app.CreateNewArc(this.firstObject, selectedObject, defaultEdge.isDirect,
|
||||
defaultEdge.weight,
|
||||
false,
|
||||
defaultEdge.upText);
|
||||
this.app.graph.edges[newEdge].useWeight = defaultEdge.useWeight;
|
||||
|
||||
this.SelectFirst();
|
||||
this.app.NeedRedraw();
|
||||
|
||||
userAction("CreateDefaultEdge");
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.SelectVertex = function(selectedObject)
|
||||
{
|
||||
if (this.firstObject)
|
||||
{
|
||||
var direct = false;
|
||||
var handler = this;
|
||||
|
||||
if (!this.app.hasDefaultEdge() || !document.getElementById('useDefaultEdge').checked) {
|
||||
this.ShowCreateEdgeDialog(this.firstObject, selectedObject, function (firstVertex, secondVertex, direct) {
|
||||
handler.AddNewEdge(secondVertex, direct);
|
||||
});
|
||||
} else {
|
||||
handler.AddDefaultEdge(selectedObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SelectSecond(selectedObject);
|
||||
}
|
||||
this.needRedraw = true;
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.MouseDown = function(pos)
|
||||
{
|
||||
$('#message').unbind();
|
||||
|
||||
var selectedObject = this.GetSelectedGraph(pos);
|
||||
if (selectedObject && (selectedObject instanceof BaseVertex))
|
||||
{
|
||||
this.SelectVertex(selectedObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SelectFirst();
|
||||
this.needRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.GetSelectedGroup = function(object)
|
||||
{
|
||||
return (object == this.firstObject) ? 1 : 0;
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.SelectFirst = function()
|
||||
{
|
||||
this.firstObject = null;
|
||||
|
||||
this.message = g_selectFirstVertexToConnect + this.GetUseDefaultEdgeCheckBox() +
|
||||
this.GetSelect2VertexMenu();
|
||||
this.message = this.AppendSpecialSctionsButton(this.message);
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.SelectSecond = function(selectedObject)
|
||||
{
|
||||
this.firstObject = selectedObject;
|
||||
this.message = g_selectSecondVertexToConnect + this.GetUseDefaultEdgeCheckBox() +
|
||||
this.GetSelect2VertexMenu();
|
||||
this.message = this.AppendSpecialSctionsButton(this.message);
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.SelectFirstVertexMenu = function(vertex1Text, vertex)
|
||||
{
|
||||
this.firstObject = null;
|
||||
this.SelectVertex(vertex);
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.UpdateFirstVertexMenu = function(vertex1Text)
|
||||
{
|
||||
if (this.firstObject)
|
||||
{
|
||||
vertex1Text.value = this.firstObject.mainText;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.SelectSecondVertexMenu = function(vertex2Text, vertex)
|
||||
{
|
||||
this.SelectVertex(vertex);
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.UpdateSecondVertexMenu = function(vertex2Text)
|
||||
{
|
||||
if (this.secondObject)
|
||||
{
|
||||
vertex2Text.value = this.secondObject.mainText;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.AppendSpecialSctionsButton = function(baseMessage)
|
||||
{
|
||||
let hasEdges = this.app.graph.hasEdges();
|
||||
|
||||
if (!hasEdges) return baseMessage;
|
||||
|
||||
let hasDirectedEdges = this.app.graph.hasDirectEdge();
|
||||
let hasUndirectedEdges = this.app.graph.hasUndirectEdge();
|
||||
|
||||
let handler = this;
|
||||
|
||||
$('#message').on('click', '#reverseAll', function() {
|
||||
handler.app.PushToStack("ReverseAllEdges");
|
||||
|
||||
handler.app.graph.reverseAllEdges();
|
||||
handler.app.redrawGraph();
|
||||
|
||||
userAction("ReverseAllEdges");
|
||||
});
|
||||
$('#message').on('click', '#makeAllUndirected', function(){
|
||||
handler.app.PushToStack("makeAllEdgesUndirected");
|
||||
|
||||
handler.app.graph.makeAllEdgesUndirected();
|
||||
handler.app.redrawGraph();
|
||||
|
||||
userAction("makeAllEdgesUndirected");
|
||||
});
|
||||
$('#message').on('click', '#makeAllDirected', function(){
|
||||
handler.app.PushToStack("makeAllEdgesDirected");
|
||||
|
||||
handler.app.graph.makeAllEdgesDirected();
|
||||
handler.app.redrawGraph();
|
||||
|
||||
userAction("makeAllEdgesDirected");
|
||||
});
|
||||
|
||||
return "<div class=\"btn-group\" style=\"float:right; position: relative; margin-left: 8px\">"
|
||||
+ "<button type=\"button\" class=\"btn btn-default btn-sm dropdown-toggle\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">"
|
||||
+ g_additionalActions + " <span class=\"caret\"></span>"
|
||||
+ " </button> "
|
||||
+ "<ul class=\"dropdown-menu dropdown-menu-right\" style=\"z-index:15; position: absolute;\">"
|
||||
+ (hasDirectedEdges ? " <li><a href=\"#\" id=\"reverseAll\">" + g_reverseAllEdges + "</a></li>" : "")
|
||||
+ (hasDirectedEdges ? " <li><a href=\"#\" id=\"makeAllUndirected\">" + g_makeAllUndirected + "</a></li>" : "")
|
||||
+ (hasUndirectedEdges ? " <li><a href=\"#\" id=\"makeAllDirected\">" + g_makeAllDirected + "</a></li>" : "")
|
||||
+ "</ul>"
|
||||
+ "</div> " + baseMessage;
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.checkUseDefaultEdge = function (elem, app)
|
||||
{
|
||||
app.setUseDefaultEdge(elem.checked);
|
||||
app.updateMessage();
|
||||
};
|
||||
|
||||
ConnectionGraphHandler.prototype.GetUseDefaultEdgeCheckBox = function() {
|
||||
if (!this.app.hasDefaultEdge()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return " <div class=\"messageSwitcher\" style=\"display:inline\">" +
|
||||
"<span id=\"switcher\"><input type=\"checkbox\" id=\"useDefaultEdge\" >" +
|
||||
"<label for=\"useDefaultEdge\" class=\"Switcher\"></label></span> <label for=\"useDefaultEdge\" class=\"switcherText\">" + g_reuseSavedEdge + "</label>" +
|
||||
"</div>";
|
||||
}
|
||||
|
||||
ConnectionGraphHandler.prototype.InitControls = function() {
|
||||
BaseHandler.prototype.InitControls.call(this)
|
||||
|
||||
if (!this.app.hasDefaultEdge()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let app = this.app;
|
||||
|
||||
$('#useDefaultEdge').unbind();
|
||||
$('#useDefaultEdge').change(function() {
|
||||
app.setUseDefaultEdge(this.checked);
|
||||
});
|
||||
$("#useDefaultEdge").prop("checked", this.app.getUseDefaultEdge());
|
||||
}
|
431
script/features/default_handler/index.js
Normal file
431
script/features/default_handler/index.js
Normal file
@ -0,0 +1,431 @@
|
||||
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Default handler.
|
||||
* Select using mouse, drag.
|
||||
*
|
||||
*/
|
||||
function DefaultHandler(app)
|
||||
{
|
||||
this.removeStack = true;
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = g_textsSelectAndMove + " <span class=\"hidden-phone\">" + g_selectGroupText + "</span>" + " <span class=\"hidden-phone\">" + g_useContextMenuText + "</span>";
|
||||
this.selectedObjects = [];
|
||||
this.dragObject = null;
|
||||
this.selectedObject = null;
|
||||
this.prevPosition = null;
|
||||
this.groupingSelect = false;
|
||||
this.selectedLogRect = false;
|
||||
this.selectedLogCtrl = false;
|
||||
this.saveUndo = false;
|
||||
|
||||
this.addContextMenu();
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
DefaultHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
// Is pressed
|
||||
DefaultHandler.prototype.pressed = false;
|
||||
// Curve change value.
|
||||
DefaultHandler.prototype.curveValue = 0.1;
|
||||
|
||||
DefaultHandler.prototype.GetSelectedVertex = function()
|
||||
{
|
||||
return (this.selectedObject instanceof BaseVertex) ? this.selectedObject : null;
|
||||
}
|
||||
|
||||
DefaultHandler.prototype.MouseMove = function(pos)
|
||||
{
|
||||
if (this.dragObject)
|
||||
{
|
||||
if (!this.saveUndo)
|
||||
{
|
||||
this.app.PushToStack("Move");
|
||||
this.saveUndo = true;
|
||||
}
|
||||
|
||||
this.dragObject.position.x = pos.x;
|
||||
this.dragObject.position.y = pos.y;
|
||||
this.needRedraw = true;
|
||||
}
|
||||
else if (this.selectedObjects.length > 0 && this.pressed && !this.groupingSelect)
|
||||
{
|
||||
if (!this.saveUndo)
|
||||
{
|
||||
this.app.PushToStack("Move");
|
||||
this.saveUndo = true;
|
||||
}
|
||||
|
||||
var offset = (new Point(pos.x, pos.y)).subtract(this.prevPosition);
|
||||
for (var i = 0; i < this.selectedObjects.length; i ++)
|
||||
{
|
||||
var object = this.selectedObjects[i];
|
||||
if (object instanceof BaseVertex)
|
||||
{
|
||||
object.position = object.position.add(offset);
|
||||
}
|
||||
}
|
||||
this.prevPosition = pos;
|
||||
this.needRedraw = true;
|
||||
}
|
||||
else if (this.pressed)
|
||||
{
|
||||
if (this.groupingSelect)
|
||||
{
|
||||
// Rect select.
|
||||
var newPos = new Point(pos.x, pos.y);
|
||||
this.app.SetSelectionRect(new Rect(newPos.min(this.prevPosition), newPos.max(this.prevPosition)));
|
||||
this.SelectObjectInRect(this.app.GetSelectionRect());
|
||||
this.needRedraw = true;
|
||||
if (!this.selectedLogRect)
|
||||
{
|
||||
userAction("GroupSelected.SelectRect");
|
||||
this.selectedLogRect = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move work space
|
||||
this.app.onCanvasMove((new Point(pos.x, pos.y)).subtract(this.prevPosition).multiply(this.app.canvasScale));
|
||||
this.needRedraw = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DefaultHandler.prototype.MouseDown = function(pos)
|
||||
{
|
||||
this.dragObject = null;
|
||||
var selectedObject = this.GetSelectedObject(pos);
|
||||
var severalSelect = g_ctrlPressed;
|
||||
|
||||
if (selectedObject == null || (!severalSelect && !this.selectedObjects.includes(selectedObject)))
|
||||
{
|
||||
this.selectedObject = null;
|
||||
this.selectedObjects = [];
|
||||
this.groupingSelect = g_ctrlPressed;
|
||||
}
|
||||
|
||||
if ((severalSelect || this.selectedObjects.includes(selectedObject)) && (this.selectedObjects.length > 0 || this.selectedObject != null) && selectedObject != null)
|
||||
{
|
||||
if (this.selectedObjects.length == 0)
|
||||
{
|
||||
this.selectedObjects.push(this.selectedObject);
|
||||
this.selectedObject = null;
|
||||
this.selectedObjects.push(selectedObject);
|
||||
}
|
||||
else if (!this.selectedObjects.includes(selectedObject))
|
||||
{
|
||||
this.selectedObjects.push(selectedObject);
|
||||
}
|
||||
else if (severalSelect && this.selectedObjects.includes(selectedObject))
|
||||
{
|
||||
var index = this.selectedObjects.indexOf(selectedObject);
|
||||
this.selectedObjects.splice(index, 1);
|
||||
}
|
||||
if (!this.selectedLogCtrl)
|
||||
{
|
||||
userAction("GroupSelected.SelectCtrl");
|
||||
this.selectedLogCtrl = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectedObject != null)
|
||||
{
|
||||
this.selectedObject = selectedObject;
|
||||
}
|
||||
if ((selectedObject instanceof BaseVertex) && selectedObject != null)
|
||||
{
|
||||
this.dragObject = selectedObject;
|
||||
this.message = g_moveCursorForMoving;
|
||||
}
|
||||
}
|
||||
this.needRedraw = true;
|
||||
this.pressed = true;
|
||||
this.prevPosition = pos;
|
||||
this.app.canvas.style.cursor = "move";
|
||||
}
|
||||
|
||||
DefaultHandler.prototype.MouseUp = function(pos)
|
||||
{
|
||||
this.saveUndo = false;
|
||||
this.message = g_textsSelectAndMove + " <span class=\"hidden-phone\">" + g_selectGroupText + "</span>" + " <span class=\"hidden-phone\">" + g_useContextMenuText + "</span>";
|
||||
this.dragObject = null;
|
||||
this.pressed = false;
|
||||
this.app.canvas.style.cursor = "auto";
|
||||
|
||||
this.app.SetSelectionRect(null);
|
||||
|
||||
this.groupingSelect = false;
|
||||
if (this.selectedObject != null && (this.selectedObject instanceof BaseVertex))
|
||||
{
|
||||
this.message = g_textsSelectAndMove
|
||||
+ "<div class=\"btn-group\" style=\"float:right;position: relative;\">"
|
||||
+ "<button type=\"button\" class=\"btn btn-default btn-sm dropdown-toggle\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">"
|
||||
+ " " + g_action + " <span class=\"caret\"></span>"
|
||||
+ " </button>"
|
||||
+ "<ul class=\"dropdown-menu dropdown-menu-right\" style=\"z-index:15; position: absolute;\">"
|
||||
+ " <li><a href=\"#\" id=\"renameButton\">" + g_renameVertex + "</a></li>"
|
||||
+ " <li><a href=\"#\" id=\"changeCommonStyle\">" + g_commonVertexStyle + "</a></li>"
|
||||
+ " <li><a href=\"#\" id=\"changeSelectedStyle\">" + g_selectedVertexStyle + "</a></li>"
|
||||
+ "</ul>"
|
||||
+ "</div>";
|
||||
|
||||
var handler = this;
|
||||
var callback = function (enumType) {
|
||||
handler.RenameVertex(enumType.GetVertexText(0), handler.selectedObject);
|
||||
userAction("RenameVertex");
|
||||
};
|
||||
$('#message').unbind();
|
||||
$('#message').on('click', '#renameButton', function(){
|
||||
var customEnum = new TextEnumVerticesCustom(handler.app);
|
||||
customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.selectedObject.mainText);
|
||||
});
|
||||
$('#message').on('click', '#changeCommonStyle', function(){
|
||||
var selectedVertices = handler.app.GetSelectedVertices();
|
||||
var setupVertexStyle = new SetupVertexStyle(handler.app);
|
||||
setupVertexStyle.show(0, selectedVertices);
|
||||
});
|
||||
$('#message').on('click', '#changeSelectedStyle', function(){
|
||||
var selectedVertices = handler.app.GetSelectedVertices();
|
||||
var setupVertexStyle = new SetupVertexStyle(handler.app);
|
||||
setupVertexStyle.show(1, selectedVertices);
|
||||
});
|
||||
}
|
||||
else if (this.selectedObject != null && (this.selectedObject instanceof BaseEdge))
|
||||
{
|
||||
this.message = g_textsSelectAndMove
|
||||
+ "<span style=\"float:right;\"><button type=\"button\" id=\"incCurvel\" class=\"btn btn-default btn-xs\"> + </button>"
|
||||
+ " " + g_curveEdge + " "
|
||||
+ "<button type=\"button\" id=\"decCurvel\" class=\"btn btn-default btn-xs\"> - </button> "
|
||||
+ "<div class=\"btn-group\" style=\"float:right;position: relative;\">"
|
||||
+ "<button type=\"button\" class=\"btn btn-default btn-sm dropdown-toggle\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">"
|
||||
+ " " + g_action + " <span class=\"caret\"></span>"
|
||||
+ " </button>"
|
||||
+ "<ul class=\"dropdown-menu dropdown-menu-right\" style=\"z-index:15; position: absolute;\">"
|
||||
+ " <li><a href=\"#\" id=\"editEdge\">" + g_editWeight + "</a></li>"
|
||||
+ " <li><a href=\"#\" id=\"changeCommonStyle\">" + g_commonEdgeStyle + "</a></li>"
|
||||
+ " <li><a href=\"#\" id=\"changeSelectedStyle\">" + g_selectedEdgeStyle + "</a></li>"
|
||||
+ "</ul>"
|
||||
+ "</div>";
|
||||
|
||||
var handler = this;
|
||||
$('#message').unbind();
|
||||
$('#message').on('click', '#editEdge', function(){
|
||||
handler.ShowEditEdgeDialog(handler.selectedObject);
|
||||
});
|
||||
|
||||
$('#message').on('click', '#incCurvel', function(){
|
||||
handler.app.PushToStack("ChangeCurvelEdge");
|
||||
|
||||
handler.selectedObject.model.ChangeCurveValue(DefaultHandler.prototype.curveValue);
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
userAction("Edge.Bend");
|
||||
});
|
||||
$('#message').on('click', '#decCurvel', function(){
|
||||
handler.app.PushToStack("ChangeCurvelEdge");
|
||||
|
||||
handler.selectedObject.model.ChangeCurveValue(-DefaultHandler.prototype.curveValue);
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
userAction("Edge.Bend");
|
||||
});
|
||||
$('#message').on('click', '#changeCommonStyle', function(){
|
||||
var selectedEdges = handler.app.GetSelectedEdges();
|
||||
var setupVertexStyle = new SetupEdgeStyle(handler.app);
|
||||
setupVertexStyle.show(0, selectedEdges);
|
||||
});
|
||||
$('#message').on('click', '#changeSelectedStyle', function(){
|
||||
var selectedEdges = handler.app.GetSelectedEdges();
|
||||
var setupVertexStyle = new SetupEdgeStyle(handler.app);
|
||||
setupVertexStyle.show(1, selectedEdges);
|
||||
});
|
||||
}
|
||||
else if (this.selectedObjects.length > 0)
|
||||
{
|
||||
this.message = g_dragGroupText + " <span class=\"hidden-phone\">" + g_selectGroupText + "</span>";
|
||||
|
||||
var hasVertices = false;
|
||||
var hasEdges = false;
|
||||
for(var i = 0; i < this.selectedObjects.length; i ++)
|
||||
{
|
||||
var object = this.selectedObjects[i];
|
||||
if (object instanceof BaseVertex)
|
||||
{
|
||||
hasVertices = true;
|
||||
}
|
||||
else if (object instanceof BaseEdge)
|
||||
{
|
||||
hasEdges = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.message = this.message + "<span style=\"float:right;position: relative;\">";
|
||||
|
||||
this.message = this.message
|
||||
+ "<button type=\"button\" id=\"DublicateSelected\" class=\"btn btn-default btn-xs\">"
|
||||
+ g_copyGroupeButton + "</button>    "
|
||||
+ "<button type=\"button\" id=\"RemoveSelected\" class=\"btn btn-default btn-xs\">"
|
||||
+ g_removeGroupeButton + "</button>"
|
||||
|
||||
this.message = this.message
|
||||
+ "     <button type=\"button\" class=\"btn btn-default btn-xs dropdown-toggle\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">"
|
||||
+ " " + g_action + " <span class=\"caret\"></span>"
|
||||
+ " </button>"
|
||||
+ "<ul class=\"dropdown-menu dropdown-menu-right\" style=\"z-index:15; position: absolute;\">";
|
||||
|
||||
if (hasEdges) {
|
||||
this.message = this.message + " <li><a href=\"#\" id=\"changeCommonStyleEdge\">" + g_commonEdgeStyle + "</a></li>";
|
||||
this.message = this.message + " <li><a href=\"#\" id=\"changeSelectedStyleEdge\">" + g_selectedEdgeStyle + "</a></li>";
|
||||
}
|
||||
|
||||
if (hasVertices) {
|
||||
this.message = this.message + " <li><a href=\"#\" id=\"changeCommonStyleVertex\">" + g_commonVertexStyle + "</a></li>";
|
||||
this.message = this.message + " <li><a href=\"#\" id=\"changeSelectedStyleVertex\">" + g_selectedVertexStyle + "</a></li>";
|
||||
}
|
||||
|
||||
this.message = this.message
|
||||
+ "</ul>"
|
||||
+ "</span>";
|
||||
|
||||
var handler = this;
|
||||
$('#message').unbind();
|
||||
|
||||
$('#message').on('click', '#DublicateSelected', function(){
|
||||
handler.app.PushToStack("DublicateSelection");
|
||||
|
||||
userAction("GroupSelected.Dublicate");
|
||||
|
||||
var newSelected = [];
|
||||
var copyVertex = {};
|
||||
|
||||
// Copy vertex
|
||||
for(var i = 0; i < handler.selectedObjects.length; i ++)
|
||||
{
|
||||
var object = handler.selectedObjects[i];
|
||||
if (object instanceof BaseVertex)
|
||||
{
|
||||
var newObject = new BaseVertex()
|
||||
newObject.copyFrom(object);
|
||||
newObject.vertexEnumType = null;
|
||||
handler.app.AddNewVertex(newObject);
|
||||
var vertex = newObject;
|
||||
var diameter = (new VertexModel()).diameter;
|
||||
vertex.position.offset(diameter, diameter);
|
||||
newSelected.push(vertex);
|
||||
copyVertex[object.id] = vertex;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy edge
|
||||
for (var i = 0; i < handler.selectedObjects.length; i ++)
|
||||
{
|
||||
var object = handler.selectedObjects[i];
|
||||
if (object instanceof BaseEdge)
|
||||
{
|
||||
var newObject = new BaseEdge()
|
||||
newObject.copyFrom(object);
|
||||
|
||||
var toNewVertex = false;
|
||||
if (newObject.vertex1.id in copyVertex)
|
||||
{
|
||||
newObject.vertex1 = copyVertex[newObject.vertex1.id];
|
||||
toNewVertex = true;
|
||||
}
|
||||
if (newObject.vertex2.id in copyVertex)
|
||||
{
|
||||
newObject.vertex2 = copyVertex[newObject.vertex2.id];
|
||||
toNewVertex = true;
|
||||
}
|
||||
|
||||
handler.app.AddNewEdge(newObject);
|
||||
if (!toNewVertex)
|
||||
{
|
||||
var neighborEdges = handler.app.graph.getNeighborEdges(newObject);
|
||||
if (neighborEdges.length >= 1)
|
||||
{
|
||||
var curve = handler.app.GetAvailableCurveValue(neighborEdges, newObject);
|
||||
newObject.model.SetCurveValue(curve);
|
||||
}
|
||||
}
|
||||
newSelected.push(newObject);
|
||||
}
|
||||
}
|
||||
|
||||
handler.selectedObjects = newSelected;
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
});
|
||||
|
||||
$('#message').on('click', '#RemoveSelected', function(){
|
||||
handler.app.PushToStack("RemoveSelection");
|
||||
|
||||
userAction("GroupSelected.Remove");
|
||||
|
||||
for(var i = 0; i < handler.selectedObjects.length; i ++)
|
||||
handler.app.DeleteObject(handler.selectedObjects[i]);
|
||||
handler.selectedObjects = [];
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
handler.message = g_textsSelectAndMove + " <span class=\"hidden-phone\">" + g_selectGroupText + "</span>";
|
||||
});
|
||||
|
||||
if (hasEdges) {
|
||||
$('#message').on('click', '#changeCommonStyleEdge', function(){
|
||||
var selectedEdges = handler.app.GetSelectedEdges();
|
||||
var setupVertexStyle = new SetupEdgeStyle(handler.app);
|
||||
setupVertexStyle.show(0, selectedEdges);
|
||||
});
|
||||
$('#message').on('click', '#changeSelectedStyleEdge', function(){
|
||||
var selectedEdges = handler.app.GetSelectedEdges();
|
||||
var setupVertexStyle = new SetupEdgeStyle(handler.app);
|
||||
setupVertexStyle.show(1, selectedEdges);
|
||||
});
|
||||
}
|
||||
|
||||
if (hasVertices) {
|
||||
$('#message').on('click', '#changeCommonStyleVertex', function(){
|
||||
var selectedVertices = handler.app.GetSelectedVertices();
|
||||
var setupVertexStyle = new SetupVertexStyle(handler.app);
|
||||
setupVertexStyle.show(0, selectedVertices);
|
||||
});
|
||||
$('#message').on('click', '#changeSelectedStyleVertex', function(){
|
||||
var selectedVertices = handler.app.GetSelectedVertices();
|
||||
var setupVertexStyle = new SetupVertexStyle(handler.app);
|
||||
setupVertexStyle.show(1, selectedVertices);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.needRedraw = true;
|
||||
}
|
||||
|
||||
DefaultHandler.prototype.GetSelectedGroup = function(object)
|
||||
{
|
||||
return (object == this.dragObject) || (object == this.selectedObject) ? 1 : 0 || this.selectedObjects.includes(object);
|
||||
}
|
||||
|
||||
DefaultHandler.prototype.SelectObjectInRect = function (rect)
|
||||
{
|
||||
this.selectedObjects = [];
|
||||
var vertices = this.app.graph.vertices;
|
||||
for (var i = 0; i < vertices.length; i ++)
|
||||
{
|
||||
if (rect.isIn(vertices[i].position) && !this.selectedObjects.includes(vertices[i]))
|
||||
this.selectedObjects.push(vertices[i]);
|
||||
}
|
||||
|
||||
// Selected Arc.
|
||||
var edges = this.app.graph.edges;
|
||||
for (var i = 0; i < edges.length; i ++)
|
||||
{
|
||||
var edge = edges[i];
|
||||
|
||||
if (rect.isIn(edge.vertex1.position) && rect.isIn(edge.vertex2.position) && !this.selectedObjects.includes(edge))
|
||||
this.selectedObjects.push(edge);
|
||||
}
|
||||
}
|
52
script/features/delete_objects_handler/index.js
Normal file
52
script/features/delete_objects_handler/index.js
Normal file
@ -0,0 +1,52 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Delete Graph handler.
|
||||
*
|
||||
*/
|
||||
function DeleteGraphHandler(app)
|
||||
{
|
||||
this.removeStack = true;
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = g_selectObjectToDelete;
|
||||
this.addContextMenu();
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
DeleteGraphHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
|
||||
DeleteGraphHandler.prototype.MouseDown = function(pos)
|
||||
{
|
||||
var selectedObject = this.GetSelectedObject(pos);
|
||||
|
||||
if (!this.app.IsCorrectObject(selectedObject))
|
||||
return;
|
||||
|
||||
this.app.PushToStack("Delete");
|
||||
this.app.DeleteObject(selectedObject);
|
||||
this.needRedraw = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Graph handler.
|
||||
*
|
||||
*/
|
||||
function DeleteAllHandler(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
DeleteAllHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
|
||||
DeleteAllHandler.prototype.clear = function()
|
||||
{
|
||||
this.app.PushToStack("DeleteAll");
|
||||
|
||||
// Selected Graph.
|
||||
this.app.graph = new Graph();
|
||||
this.app.savedGraphName = "";
|
||||
this.needRedraw = true;
|
||||
}
|
10
script/features/draw_graph/api/index.js
Normal file
10
script/features/draw_graph/api/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
let modulDir = "features/draw_graph/";
|
||||
|
||||
doInclude ([
|
||||
include ("model/BaseBackgroundDrawer.js", modulDir),
|
||||
include ("model/BaseEdgeDrawer.js", modulDir),
|
||||
include ("model/BaseVertexDrawer.js", modulDir)
|
||||
])
|
||||
|
||||
}
|
0
script/EnumVertices.js → script/features/enum_vertices/EnumVertices.js
Executable file → Normal file
0
script/EnumVertices.js → script/features/enum_vertices/EnumVertices.js
Executable file → Normal file
61
script/features/group_rename_handler/index.js
Normal file
61
script/features/group_rename_handler/index.js
Normal file
@ -0,0 +1,61 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Groupe rename vertices.
|
||||
*
|
||||
*/
|
||||
function GroupRenameVertices(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
GroupRenameVertices.prototype = Object.create(BaseHandler.prototype);
|
||||
// First selected.
|
||||
GroupRenameVertices.prototype.firstObject = null;
|
||||
// Path
|
||||
GroupRenameVertices.prototype.pathObjects = null;
|
||||
|
||||
GroupRenameVertices.prototype.show = function()
|
||||
{
|
||||
var handler = this;
|
||||
var dialogButtons = {};
|
||||
var graph = this.app.graph;
|
||||
var app = this.app;
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
app.PushToStack("Rename");
|
||||
|
||||
var titlesList = $( "#VertextTitleList" ).val().split('\n');
|
||||
for (i = 0; i < Math.min(graph.vertices.length, titlesList.length); i ++)
|
||||
{
|
||||
graph.vertices[i].mainText = titlesList[i];
|
||||
}
|
||||
app.redrawGraph();
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
dialogButtons[g_cancel] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
var titleList = "";
|
||||
for (i = 0; i < graph.vertices.length; i ++)
|
||||
{
|
||||
titleList = titleList + graph.vertices[i].mainText + "\n";
|
||||
}
|
||||
|
||||
$( "#VertextTitleList" ).val(titleList);
|
||||
|
||||
$( "#GroupRenameDialog" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_groupRename,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
}
|
52
script/features/saved_graph_handler/index.js
Normal file
52
script/features/saved_graph_handler/index.js
Normal file
@ -0,0 +1,52 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Save dialog Graph handler.
|
||||
*
|
||||
*/
|
||||
function SavedDialogGraphHandler(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
SavedDialogGraphHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
// First selected.
|
||||
SavedDialogGraphHandler.prototype.firstObject = null;
|
||||
// Path
|
||||
SavedDialogGraphHandler.prototype.pathObjects = null;
|
||||
// Objects.
|
||||
SavedDialogGraphHandler.prototype.objects = null;
|
||||
|
||||
SavedDialogGraphHandler.prototype.show = function(object)
|
||||
{
|
||||
this.app.SaveGraphOnDisk();
|
||||
|
||||
var dialogButtons = {};
|
||||
|
||||
dialogButtons[g_close] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
document.getElementById('GraphName').value = "http://" + window.location.host + window.location.pathname +
|
||||
"?graph=" + this.app.GetGraphName();
|
||||
|
||||
document.getElementById('GraphName').select();
|
||||
|
||||
document.getElementById("ShareSavedGraph").innerHTML =
|
||||
document.getElementById("ShareSavedGraph").innerHTML.replace(/graph=([A-Za-z]*)/g, "graph=" + this.app.GetGraphName());
|
||||
|
||||
$( "#saveDialog" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_save_dialog,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
|
||||
}
|
94
script/features/saved_graph_image_handler/index.js
Normal file
94
script/features/saved_graph_image_handler/index.js
Normal file
@ -0,0 +1,94 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Save dialog Graph handler.
|
||||
*
|
||||
*/
|
||||
function SavedDialogGraphImageHandler(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
this.imageName = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
SavedDialogGraphImageHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
// First selected.
|
||||
SavedDialogGraphImageHandler.prototype.firstObject = null;
|
||||
// Path
|
||||
SavedDialogGraphImageHandler.prototype.pathObjects = null;
|
||||
// Objects.
|
||||
SavedDialogGraphImageHandler.prototype.objects = null;
|
||||
|
||||
SavedDialogGraphImageHandler.prototype.showDialogCallback = function (imageExtension)
|
||||
{
|
||||
var dialogButtons = {};
|
||||
|
||||
dialogButtons[g_close] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
var fileLocation = "tmp/saved/" + this.imageName.substr(0, 2) + "/"+ this.imageName + "." + imageExtension
|
||||
|
||||
document.getElementById("showSavedImageGraph").src = "/" + fileLocation;
|
||||
document.getElementById("showSavedImageGraphRef").href = "/" + fileLocation;
|
||||
//document.getElementById("showSavedImageGraph").src = document.getElementById("showSavedImageGraph").src.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation);
|
||||
document.getElementById("ShareSavedImageGraph").innerHTML =
|
||||
document.getElementById("ShareSavedImageGraph").innerHTML.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation);
|
||||
|
||||
document.getElementById("SaveImageLinks").innerHTML =
|
||||
document.getElementById("SaveImageLinks").innerHTML.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation);
|
||||
|
||||
$( "#saveImageDialog" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_save_image_dialog,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
SavedDialogGraphImageHandler.prototype.showWorkspace = function()
|
||||
{
|
||||
var object = this;
|
||||
var callback = function() {
|
||||
object.showDialogCallback("png");
|
||||
};
|
||||
|
||||
this.imageName = this.app.SaveGraphImageOnDisk(callback);
|
||||
}
|
||||
|
||||
SavedDialogGraphImageHandler.prototype.showFullgraph = function()
|
||||
{
|
||||
var object = this;
|
||||
var callback = function() {
|
||||
object.showDialogCallback("png");
|
||||
};
|
||||
|
||||
this.imageName = this.app.SaveFullGraphImageOnDisk(callback, false);
|
||||
}
|
||||
|
||||
SavedDialogGraphImageHandler.prototype.showPrint = function()
|
||||
{
|
||||
var object = this;
|
||||
var callback = function() {
|
||||
object.showDialogCallback("png");
|
||||
};
|
||||
|
||||
this.imageName = this.app.SaveFullGraphImageOnDisk(callback, true);
|
||||
}
|
||||
|
||||
SavedDialogGraphImageHandler.prototype.showSvg = function()
|
||||
{
|
||||
var object = this;
|
||||
var callback = function() {
|
||||
object.showDialogCallback("svg");
|
||||
};
|
||||
|
||||
this.imageName = this.app.SaveSVGGraphOnDisk(callback);
|
||||
}
|
8
script/features/serialization/api/index.js
Normal file
8
script/features/serialization/api/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
let modulDir = "features/serialization/";
|
||||
|
||||
doInclude ([
|
||||
include ("model/GraphMLCreator.js", modulDir)
|
||||
])
|
||||
|
||||
}
|
167
script/features/setup_background_style/index.js
Normal file
167
script/features/setup_background_style/index.js
Normal file
@ -0,0 +1,167 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Setup Background Style rename vertices.
|
||||
*
|
||||
*/
|
||||
function SetupBackgroundStyle(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
this.maxImageSize = 2048;
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
SetupBackgroundStyle.prototype = Object.create(BaseHandler.prototype);
|
||||
|
||||
|
||||
SetupBackgroundStyle.prototype.handleImportBackgroundFile = function(files, updateBackgroundCallback) {
|
||||
var graphFileToLoad = files[0];
|
||||
var re = /(?:\.([^.]+))?$/;
|
||||
var imageExtension = re.exec(graphFileToLoad.name)[1].toLowerCase();
|
||||
|
||||
if (!(imageExtension == "png" || imageExtension == "jpg" || imageExtension == "jpeg")) {
|
||||
$("#UploadBackgroundImageError").html(g_wrongImageFormatPNGAndJPEG);
|
||||
$("#UploadBackgroundImageError").show();
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function(fileLoadedEvent){
|
||||
var textFromFileLoaded = fileLoadedEvent.target.result;
|
||||
var image = new Image();
|
||||
image.onload = function() {
|
||||
console.log(this.width + 'x' + this.height);
|
||||
if (this.width > self.maxImageSize || this.height > self.maxImageSize) {
|
||||
$("#UploadBackgroundImageError").html(formatString(g_wrongImageSizeP1, [self.maxImageSize]));
|
||||
$("#UploadBackgroundImageError").show();
|
||||
return;
|
||||
}
|
||||
updateBackgroundCallback(image);
|
||||
}
|
||||
image.src = 'data:image/' + imageExtension + ';base64' + textFromFileLoaded;
|
||||
ImportBackgroundImage.value = "";
|
||||
};
|
||||
|
||||
fileReader.readAsDataURL(graphFileToLoad);
|
||||
}
|
||||
|
||||
SetupBackgroundStyle.prototype.show = function()
|
||||
{
|
||||
var handler = this;
|
||||
var dialogButtons = {};
|
||||
var graph = this.app.graph;
|
||||
var app = this.app;
|
||||
var style = FullObjectCopy(app.backgroundCommonStyle);
|
||||
|
||||
var fillFields = function()
|
||||
{
|
||||
$( "#backgroundColor" ).val(style.commonColor);
|
||||
$( "#backgroundTransporent" ).val(style.commonOpacity);
|
||||
}
|
||||
|
||||
var redrawVertex = function()
|
||||
{
|
||||
style.commonColor = $( "#backgroundColor" ).val();
|
||||
style.commonOpacity = $( "#backgroundTransporent" ).val();
|
||||
|
||||
var canvas = document.getElementById( "BackgroundPreview" );
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
context.save();
|
||||
let bestScale = 1.0;
|
||||
if (style.image != null) {
|
||||
let wScale = canvas.width / style.image.width;
|
||||
let hScale = canvas.height / style.image.height;
|
||||
bestScale = Math.min(wScale, hScale);
|
||||
context.scale(bestScale, bestScale);
|
||||
}
|
||||
var backgroundDrawer = new BaseBackgroundDrawer(context);
|
||||
backgroundDrawer.Draw(style, canvas.width, canvas.height, new Point(0, 0), bestScale);
|
||||
|
||||
context.restore();
|
||||
|
||||
if (style.image != null) {
|
||||
$( "#RemoveBackgroundFile" ).show();
|
||||
} else {
|
||||
$( "#RemoveBackgroundFile" ).hide();
|
||||
}
|
||||
}
|
||||
|
||||
var loadFile = function() {
|
||||
userAction("background_loadFromFile");
|
||||
|
||||
if (ImportBackgroundImage) {
|
||||
ImportBackgroundImage.click();
|
||||
}
|
||||
}
|
||||
|
||||
var updateBackgroundImage = function(image) {
|
||||
style.image = image;
|
||||
$("#UploadBackgroundImageError").hide();
|
||||
redrawVertex();
|
||||
}
|
||||
|
||||
var clearBackgroundImage = function() {
|
||||
style.image = null;
|
||||
$("#UploadBackgroundImageError").hide();
|
||||
redrawVertex();
|
||||
}
|
||||
|
||||
dialogButtons[g_default] =
|
||||
{
|
||||
text : g_default,
|
||||
class : "MarginLeft",
|
||||
click : function() {
|
||||
|
||||
app.PushToStack("ChangeBackground");
|
||||
|
||||
app.ResetBackgroundStyle();
|
||||
app.redrawGraph();
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
};
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
app.PushToStack("ChangeBackground");
|
||||
app.SetBackgroundStyle(style);
|
||||
app.redrawGraph();
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
dialogButtons[g_cancel] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
fillFields();
|
||||
|
||||
$( "#SetupBackgroundStyleDialog" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_backgroundStyle,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
|
||||
try {
|
||||
redrawVertex();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
$( "#backgroundColor" ).unbind();
|
||||
$( "#backgroundTransporent" ).unbind();
|
||||
$( "#LoadBackgroundFile" ).unbind();
|
||||
$( "#ImportBackgroundImage" ).unbind();
|
||||
$( "#RemoveBackgroundFile" ).unbind();
|
||||
|
||||
$( "#backgroundColor" ).change(redrawVertex);
|
||||
$( "#backgroundTransporent" ).change(redrawVertex);
|
||||
$( "#LoadBackgroundFile" ).click(loadFile);
|
||||
$( "#ImportBackgroundImage" ).change( function () {handler.handleImportBackgroundFile(this.files, updateBackgroundImage);});
|
||||
$( "#RemoveBackgroundFile" ).click(clearBackgroundImage);
|
||||
}
|
295
script/features/setup_edge_style/index.js
Normal file
295
script/features/setup_edge_style/index.js
Normal file
@ -0,0 +1,295 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Setup Vertex Style rename vertices.
|
||||
*
|
||||
*/
|
||||
function SetupEdgeStyle(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
SetupEdgeStyle.prototype = Object.create(BaseHandler.prototype);
|
||||
|
||||
SetupEdgeStyle.prototype.show = function(index, selectedEdges)
|
||||
{
|
||||
var handler = this;
|
||||
var dialogButtons = {};
|
||||
var graph = this.app.graph;
|
||||
var app = this.app;
|
||||
this.forAll = selectedEdges == null;
|
||||
var forAll = this.forAll;
|
||||
|
||||
var self = this;
|
||||
|
||||
var applyIndex = function(index)
|
||||
{
|
||||
self.index = index;
|
||||
var originStyle = (self.index == 0 ? app.edgeCommonStyle : app.edgeSelectedStyles[self.index - 1]);
|
||||
if (!forAll)
|
||||
{
|
||||
originStyle = selectedEdges[0].getStyleFor(self.index);
|
||||
}
|
||||
self.style = FullObjectCopy(originStyle);
|
||||
}
|
||||
|
||||
applyIndex(index);
|
||||
|
||||
var fillFields = function()
|
||||
{
|
||||
var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedEdges[0]);
|
||||
|
||||
$( "#edgeFillColor" ).val(fullStyle.fillStyle);
|
||||
$( "#edgeStrokeColor" ).val(fullStyle.strokeStyle);
|
||||
$( "#edgeTextColor" ).val(fullStyle.weightText);
|
||||
$( "#edgeStyle" ).val(fullStyle.lineDash);
|
||||
$( "#edgeWidth" ).val(forAll ? app.GetDefaultEdgeWidth() : selectedEdges[0].model.width);
|
||||
|
||||
$( "#weightEdgeTextColor" ).val(fullStyle.additionalTextColor);
|
||||
$( "#weightTextPosition" ).val(fullStyle.weightPosition);
|
||||
|
||||
if (self.index > 0 || self.index == "all")
|
||||
{
|
||||
$( "#EdgeSelectedIndexForm" ).show();
|
||||
$( "#edgeSelectedIndex" ).val(self.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
$( "#EdgeSelectedIndexForm" ).hide();
|
||||
}
|
||||
|
||||
// Fill color presets.
|
||||
var stylesArray = [];
|
||||
stylesArray.push(app.edgeCommonStyle);
|
||||
|
||||
for (i = 0; i < app.edgeSelectedStyles.length; i ++)
|
||||
stylesArray.push(app.edgeSelectedStyles[i]);
|
||||
|
||||
var colorSet = {};
|
||||
for (i = 0; i < stylesArray.length; i ++)
|
||||
{
|
||||
var style = stylesArray[i];
|
||||
if (style.hasOwnProperty('strokeStyle'))
|
||||
colorSet[style.strokeStyle] = 1;
|
||||
if (style.hasOwnProperty('fillStyle'))
|
||||
colorSet[style.fillStyle] = 1;
|
||||
if (style.hasOwnProperty('additionalTextColor'))
|
||||
colorSet[style.additionalTextColor] = 1;
|
||||
}
|
||||
|
||||
$("#edgeFillColorPreset").find('option').remove();
|
||||
$("#weightEdgeTextColorPreset").find('option').remove();
|
||||
$("#edgeTextColorPreset").find('option').remove();
|
||||
$("#edgeStrokeColorPreset").find('option').remove();
|
||||
for (const property in colorSet)
|
||||
{
|
||||
$("#edgeFillColorPreset").append(new Option(property));
|
||||
$("#weightEdgeTextColorPreset").append(new Option(property));
|
||||
$("#edgeTextColorPreset").append(new Option(property));
|
||||
$("#edgeStrokeColorPreset").append(new Option(property));
|
||||
}
|
||||
}
|
||||
|
||||
var redrawVertex = function()
|
||||
{
|
||||
var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedEdges[0]);
|
||||
|
||||
if (fullStyle.fillStyle != $( "#edgeFillColor" ).val())
|
||||
self.style.fillStyle = $( "#edgeFillColor" ).val();
|
||||
|
||||
if (fullStyle.strokeStyle != $( "#edgeStrokeColor" ).val())
|
||||
self.style.strokeStyle = $( "#edgeStrokeColor" ).val();
|
||||
|
||||
if (fullStyle.weightText != $( "#edgeTextColor" ).val())
|
||||
self.style.weightText = $( "#edgeTextColor" ).val();
|
||||
|
||||
if (fullStyle.lineDash != $( "#edgeStyle" ).val())
|
||||
self.style.lineDash = $( "#edgeStyle" ).val();
|
||||
|
||||
if (fullStyle.additionalTextColor != $( "#weightEdgeTextColor" ).val())
|
||||
self.style.additionalTextColor = $( "#weightEdgeTextColor" ).val();
|
||||
|
||||
if (fullStyle.weightPosition != $( "#weightTextPosition" ).val())
|
||||
self.style.weightPosition = $( "#weightTextPosition" ).val();
|
||||
|
||||
var edgeWidth = parseInt($( "#edgeWidth" ).val());
|
||||
|
||||
var canvas = document.getElementById( "EdgePreview" );
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
context.save();
|
||||
|
||||
var backgroundDrawer = new BaseBackgroundDrawer(context);
|
||||
backgroundDrawer.Draw(app.backgroundCommonStyle, canvas.width, canvas.height, new Point(0, 0), 1.0);
|
||||
|
||||
var graphDrawer = new BaseEdgeDrawer(context);
|
||||
var baseVertex1 = new BaseVertex(0, canvas.height / 2, new BaseEnumVertices(this));
|
||||
var baseVertex2 = new BaseVertex(canvas.width, canvas.height / 2, new BaseEnumVertices(this));
|
||||
|
||||
baseVertex1.currentStyle = baseVertex1.getStyleFor(0);
|
||||
baseVertex2.currentStyle = baseVertex2.getStyleFor(0);
|
||||
|
||||
var baseEdge = new BaseEdge(baseVertex1, baseVertex2, true, 10, "Text");
|
||||
|
||||
if (!forAll)
|
||||
baseEdge.ownStyles = selectedEdges[0].ownStyles;
|
||||
|
||||
baseEdge.model.width = edgeWidth;
|
||||
|
||||
graphDrawer.Draw(baseEdge, self.style.GetStyle({}, baseEdge));
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
var changeIndex = function()
|
||||
{
|
||||
var val = $( "#edgeSelectedIndex" ).val();
|
||||
if (val == "all")
|
||||
{
|
||||
applyIndex(1);
|
||||
self.index = "all";
|
||||
fillFields();
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = parseInt(val);
|
||||
self.index = index;
|
||||
applyIndex(index);
|
||||
fillFields();
|
||||
}
|
||||
|
||||
redrawVertex();
|
||||
}
|
||||
|
||||
var applyWidth = function(width)
|
||||
{
|
||||
if (forAll)
|
||||
{
|
||||
app.SetDefaultEdgeWidth(width);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedEdges.forEach(function(edge) {
|
||||
edge.model.width = width;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
dialogButtons[g_default] =
|
||||
{
|
||||
text : g_default,
|
||||
class : "MarginLeft",
|
||||
click : function() {
|
||||
app.PushToStack("ChangeStyle");
|
||||
|
||||
applyWidth(forAll ? (new EdgeModel()).width : app.GetDefaultEdgeWidth());
|
||||
var indexes = [];
|
||||
if (self.index == "all")
|
||||
{
|
||||
for (i = 0; i < app.edgeSelectedStyles.length; i ++)
|
||||
indexes.push(i + 1);
|
||||
}
|
||||
else
|
||||
indexes.push(self.index);
|
||||
|
||||
if (forAll)
|
||||
{
|
||||
indexes.forEach(function(index) {
|
||||
app.ResetEdgeStyle(index);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedEdges.forEach(function(edge) {
|
||||
indexes.forEach(function(index) {
|
||||
edge.resetOwnStyle(index);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
app.redrawGraph();
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
};
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
|
||||
app.PushToStack("ChangeStyle");
|
||||
|
||||
applyWidth(parseInt($( "#edgeWidth" ).val()));
|
||||
|
||||
var indexes = [];
|
||||
if (self.index == "all")
|
||||
{
|
||||
indexes.push({index : 1, style : self.style});
|
||||
|
||||
for (i = 1; i < app.edgeSelectedStyles.length; i ++)
|
||||
{
|
||||
var style = (new BaseEdgeStyle());
|
||||
style.baseStyles.push("selected");
|
||||
indexes.push({index : i + 1, style : style});
|
||||
}
|
||||
|
||||
self.style.baseStyles = [];
|
||||
self.style.baseStyles = self.style.baseStyles.concat((new SelectedEdgeStyle0()).baseStyles);
|
||||
}
|
||||
else
|
||||
indexes.push({index : self.index, style : self.style});
|
||||
|
||||
if (forAll)
|
||||
{
|
||||
indexes.forEach(function(index) {
|
||||
app.SetEdgeStyle(index.index, index.style);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedEdges.forEach(function(edge) {
|
||||
indexes.forEach(function(index) {
|
||||
edge.setOwnStyle(index.index, index.style);
|
||||
});
|
||||
});
|
||||
}
|
||||
app.redrawGraph();
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
dialogButtons[g_cancel] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
fillFields();
|
||||
|
||||
$( "#SetupEdgeStyleDialog" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_edgeDraw,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
|
||||
redrawVertex();
|
||||
|
||||
$( "#edgeFillColor" ).unbind();
|
||||
$( "#edgeStrokeColor" ).unbind();
|
||||
$( "#edgeTextColor" ).unbind();
|
||||
$( "#edgeStyle" ).unbind();
|
||||
$( "#edgeWidth" ).unbind();
|
||||
$( "#weightEdgeTextColor" ).unbind();
|
||||
$( "#weightTextPosition" ).unbind();
|
||||
$( "#edgeSelectedIndex" ).unbind();
|
||||
|
||||
$( "#edgeFillColor" ).change(redrawVertex);
|
||||
$( "#edgeStrokeColor" ).change(redrawVertex);
|
||||
$( "#edgeTextColor" ).change(redrawVertex);
|
||||
$( "#edgeStyle" ).change(redrawVertex);
|
||||
$( "#edgeWidth" ).change(redrawVertex);
|
||||
$( "#weightEdgeTextColor" ).change(redrawVertex);
|
||||
$( "#weightTextPosition" ).change(redrawVertex);
|
||||
$( "#edgeSelectedIndex" ).change(changeIndex);
|
||||
}
|
299
script/features/setup_vertex_style/index.js
Normal file
299
script/features/setup_vertex_style/index.js
Normal file
@ -0,0 +1,299 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Setup Vertex Style rename vertices.
|
||||
*
|
||||
*/
|
||||
function SetupVertexStyle(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
SetupVertexStyle.prototype = Object.create(BaseHandler.prototype);
|
||||
|
||||
SetupVertexStyle.prototype.show = function(index, selectedVertices)
|
||||
{
|
||||
var handler = this;
|
||||
var dialogButtons = {};
|
||||
var graph = this.app.graph;
|
||||
var app = this.app;
|
||||
this.forAll = selectedVertices == null;
|
||||
var forAll = this.forAll;
|
||||
var self = this;
|
||||
|
||||
var applyIndex = function(index)
|
||||
{
|
||||
self.index = index;
|
||||
self.originStyle = (self.index == 0 ? app.vertexCommonStyle : app.vertexSelectedVertexStyles[self.index - 1]);
|
||||
if (!forAll)
|
||||
{
|
||||
self.originStyle = selectedVertices[0].getStyleFor(self.index);
|
||||
}
|
||||
self.style = FullObjectCopy(self.originStyle);
|
||||
}
|
||||
|
||||
applyIndex(index);
|
||||
|
||||
var fillFields = function()
|
||||
{
|
||||
var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedVertices[0]);
|
||||
|
||||
$( "#vertexFillColor" ).val(fullStyle.fillStyle);
|
||||
$( "#vertexStrokeColor" ).val(fullStyle.strokeStyle);
|
||||
$( "#vertexTextColor" ).val(fullStyle.mainTextColor);
|
||||
$( "#upVertexTextColor" ).val(fullStyle.upTextColor);
|
||||
$( "#vertexStrokeSize" ).val(fullStyle.lineWidth);
|
||||
$( "#vertexShape" ).val(fullStyle.shape);
|
||||
$( "#vertexSize" ).val(forAll ? app.GetDefaultVertexSize() : selectedVertices[0].model.diameter);
|
||||
$( "#commonTextPosition" ).val(fullStyle.commonTextPosition);
|
||||
|
||||
if (self.index > 0 || self.index == "all")
|
||||
{
|
||||
$( "#VertexSelectedIndexForm" ).show();
|
||||
$( "#vertexSelectedIndex" ).val(self.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
$( "#VertexSelectedIndexForm" ).hide();
|
||||
}
|
||||
|
||||
// Fill color presets.
|
||||
var stylesArray = [];
|
||||
stylesArray.push(app.vertexCommonStyle);
|
||||
|
||||
for (i = 0; i < app.vertexSelectedVertexStyles.length; i ++)
|
||||
stylesArray.push(app.vertexSelectedVertexStyles[i]);
|
||||
|
||||
var colorSet = {};
|
||||
for (i = 0; i < stylesArray.length; i ++)
|
||||
{
|
||||
var style = stylesArray[i];
|
||||
if (style.hasOwnProperty('strokeStyle'))
|
||||
colorSet[style.strokeStyle] = 1;
|
||||
if (style.hasOwnProperty('fillStyle'))
|
||||
colorSet[style.fillStyle] = 1;
|
||||
if (style.hasOwnProperty('mainTextColor'))
|
||||
colorSet[style.mainTextColor] = 1;
|
||||
if (style.hasOwnProperty('upTextColor'))
|
||||
colorSet[style.upTextColor] = 1;
|
||||
}
|
||||
|
||||
$("#vertexFillColorPreset").find('option').remove();
|
||||
$("#upVertexTextColorPreset").find('option').remove();
|
||||
$("#vertexTextColorPreset").find('option').remove();
|
||||
$("#vertexStrokeColorPreset").find('option').remove();
|
||||
for (const property in colorSet)
|
||||
{
|
||||
$("#vertexFillColorPreset").append(new Option(property));
|
||||
$("#upVertexTextColorPreset").append(new Option(property));
|
||||
$("#vertexTextColorPreset").append(new Option(property));
|
||||
$("#vertexStrokeColorPreset").append(new Option(property));
|
||||
}
|
||||
}
|
||||
|
||||
var redrawVertex = function()
|
||||
{
|
||||
var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedVertices[0]);
|
||||
|
||||
if (fullStyle.fillStyle != $( "#vertexFillColor" ).val())
|
||||
self.style.fillStyle = $( "#vertexFillColor" ).val();
|
||||
|
||||
if (fullStyle.strokeStyle != $( "#vertexStrokeColor" ).val())
|
||||
self.style.strokeStyle = $( "#vertexStrokeColor" ).val();
|
||||
|
||||
if (fullStyle.mainTextColor != $( "#vertexTextColor" ).val())
|
||||
self.style.mainTextColor = $( "#vertexTextColor" ).val();
|
||||
|
||||
if (fullStyle.lineWidth != $( "#vertexStrokeSize" ).val())
|
||||
self.style.lineWidth = parseInt($( "#vertexStrokeSize" ).val());
|
||||
|
||||
if (fullStyle.shape != $( "#vertexShape" ).val())
|
||||
self.style.shape = parseInt($( "#vertexShape" ).val());
|
||||
|
||||
if (fullStyle.upTextColor != $( "#upVertexTextColor" ).val())
|
||||
self.style.upTextColor = $( "#upVertexTextColor" ).val();
|
||||
|
||||
if (fullStyle.commonTextPosition != $( "#commonTextPosition" ).val())
|
||||
self.style.commonTextPosition = $( "#commonTextPosition" ).val();
|
||||
|
||||
var diameter = parseInt($( "#vertexSize" ).val());
|
||||
|
||||
var canvas = document.getElementById( "VertexPreview" );
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
context.save();
|
||||
|
||||
var backgroundDrawer = new BaseBackgroundDrawer(context);
|
||||
backgroundDrawer.Draw(app.backgroundCommonStyle, canvas.width, canvas.height, new Point(0, 0), 1.0);
|
||||
|
||||
var graphDrawer = new BaseVertexDrawer(context);
|
||||
var baseVertex = new BaseVertex(canvas.width / 2, canvas.height / 2, new BaseEnumVertices(this));
|
||||
baseVertex.mainText = "1";
|
||||
baseVertex.upText = "Up Text";
|
||||
baseVertex.model.diameter = diameter;
|
||||
|
||||
if (!forAll)
|
||||
baseVertex.ownStyles = selectedVertices[0].ownStyles;
|
||||
|
||||
graphDrawer.Draw(baseVertex, self.style.GetStyle({}, baseVertex));
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
var changeIndex = function()
|
||||
{
|
||||
var val = $( "#vertexSelectedIndex" ).val();
|
||||
if (val == "all")
|
||||
{
|
||||
applyIndex(1);
|
||||
self.index = "all";
|
||||
fillFields();
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = parseInt(val);
|
||||
self.index = index;
|
||||
applyIndex(index);
|
||||
fillFields();
|
||||
}
|
||||
redrawVertex();
|
||||
}
|
||||
|
||||
var applyDiameter = function(diameter)
|
||||
{
|
||||
if (forAll)
|
||||
{
|
||||
app.SetDefaultVertexSize(diameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedVertices.forEach(function(vertex) {
|
||||
vertex.model.diameter = diameter;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
dialogButtons[g_default] =
|
||||
{
|
||||
text : g_default,
|
||||
class : "MarginLeft",
|
||||
click : function() {
|
||||
|
||||
app.PushToStack("ChangeStyle");
|
||||
|
||||
applyDiameter(forAll ? (new VertexModel()).diameter : app.GetDefaultVertexSize());
|
||||
|
||||
var indexes = [];
|
||||
if (self.index == "all")
|
||||
{
|
||||
for (i = 0; i < app.vertexSelectedVertexStyles.length; i ++)
|
||||
indexes.push(i + 1);
|
||||
}
|
||||
else
|
||||
indexes.push(self.index);
|
||||
|
||||
|
||||
if (forAll)
|
||||
{
|
||||
indexes.forEach(function(index) {
|
||||
app.ResetVertexStyle(index);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedVertices.forEach(function(vertex) {
|
||||
indexes.forEach(function(index) {
|
||||
vertex.resetOwnStyle(index);
|
||||
});
|
||||
});
|
||||
}
|
||||
app.redrawGraph();
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
};
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
|
||||
app.PushToStack("ChangeStyle");
|
||||
|
||||
applyDiameter(parseInt($( "#vertexSize" ).val()));
|
||||
|
||||
var indexes = [];
|
||||
if (self.index == "all")
|
||||
{
|
||||
indexes.push({index : 1, style : self.style});
|
||||
for (i = 1; i < app.vertexSelectedVertexStyles.length; i ++)
|
||||
{
|
||||
var style = (new BaseVertexStyle());
|
||||
style.baseStyles.push("selected");
|
||||
indexes.push({index : i + 1, style : style});
|
||||
}
|
||||
|
||||
self.style.baseStyles = [];
|
||||
self.style.baseStyles = self.style.baseStyles.concat((new SelectedVertexStyle0()).baseStyles);
|
||||
}
|
||||
else
|
||||
indexes.push({index : self.index, style : self.style});
|
||||
|
||||
if (forAll)
|
||||
{
|
||||
indexes.forEach(function(index) {
|
||||
app.SetVertexStyle(index.index, index.style);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (JSON.stringify(self.originStyle) !== JSON.stringify(self.style))
|
||||
{
|
||||
selectedVertices.forEach(function(vertex) {
|
||||
indexes.forEach(function(index) {
|
||||
vertex.setOwnStyle(index.index, index.style);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
app.redrawGraph();
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
dialogButtons[g_cancel] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
fillFields();
|
||||
|
||||
$( "#SetupVertexStyleDialog" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_vertexDraw,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
|
||||
redrawVertex();
|
||||
|
||||
$( "#vertexFillColor" ).unbind();
|
||||
$( "#vertexStrokeColor" ).unbind();
|
||||
$( "#vertexTextColor" ).unbind();
|
||||
$( "#upVertexTextColor" ).unbind();
|
||||
$( "#vertexStrokeSize" ).unbind();
|
||||
$( "#vertexShape" ).unbind();
|
||||
$( "#vertexSize" ).unbind();
|
||||
$( "#commonTextPosition" ).unbind();
|
||||
$( "#vertexSelectedIndex" ).unbind();
|
||||
|
||||
$( "#vertexFillColor" ).change(redrawVertex);
|
||||
$( "#vertexStrokeColor" ).change(redrawVertex);
|
||||
$( "#vertexTextColor" ).change(redrawVertex);
|
||||
$( "#vertexStrokeSize" ).change(redrawVertex);
|
||||
$( "#vertexShape" ).change(redrawVertex);
|
||||
$( "#vertexSize" ).change(redrawVertex);
|
||||
$( "#upVertexTextColor" ).change(redrawVertex);
|
||||
$( "#commonTextPosition" ).change(redrawVertex);
|
||||
$( "#vertexSelectedIndex" ).change(changeIndex);
|
||||
}
|
66
script/features/show_adjacency_matrix/index.js
Normal file
66
script/features/show_adjacency_matrix/index.js
Normal file
@ -0,0 +1,66 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Save/Load graph from matrix.
|
||||
*
|
||||
*/
|
||||
function ShowAdjacencyMatrix(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
ShowAdjacencyMatrix.prototype = Object.create(BaseHandler.prototype);
|
||||
// First selected.
|
||||
ShowAdjacencyMatrix.prototype.firstObject = null;
|
||||
// Path
|
||||
ShowAdjacencyMatrix.prototype.pathObjects = null;
|
||||
|
||||
ShowAdjacencyMatrix.prototype.show = function()
|
||||
{
|
||||
var handler = this;
|
||||
var dialogButtons = {};
|
||||
|
||||
$('#AdjacencyMatrixField').unbind();
|
||||
$( "#AdjacencyMatrixField" ).on('keyup change', function (eventObject)
|
||||
{
|
||||
if (!handler.app.TestAdjacencyMatrix($( "#AdjacencyMatrixField" ).val(), [], []))
|
||||
{
|
||||
$( "#BadMatrixFormatMessage" ).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$( "#BadMatrixFormatMessage" ).hide();
|
||||
}
|
||||
});
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
handler.app.PushToStack("ChangeAdjacencyMatrix");
|
||||
handler.app.SetAdjacencyMatrixSmart($( "#AdjacencyMatrixField" ).val());
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
dialogButtons[g_cancel] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
$( "#AdjacencyMatrixField" ).val(this.app.GetAdjacencyMatrix());
|
||||
$( "#BadMatrixFormatMessage" ).hide();
|
||||
|
||||
if (this.app.graph.isMulti())
|
||||
$( "#AdjacencyMatrixMultiGraphDesc").show();
|
||||
else
|
||||
$( "#AdjacencyMatrixMultiGraphDesc").hide();
|
||||
|
||||
$( "#adjacencyMatrix" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_adjacencyMatrixText,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
}
|
77
script/features/show_distance_matrix/index.js
Normal file
77
script/features/show_distance_matrix/index.js
Normal file
@ -0,0 +1,77 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Show distance matrix.
|
||||
*
|
||||
*/
|
||||
function ShowDistanceMatrix(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.app = app;
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
ShowDistanceMatrix.prototype = Object.create(BaseHandler.prototype);
|
||||
// First selected.
|
||||
ShowDistanceMatrix.prototype.firstObject = null;
|
||||
// Path
|
||||
ShowDistanceMatrix.prototype.pathObjects = null;
|
||||
|
||||
ShowDistanceMatrix.prototype.GetIncidenceMatrix = function (rawMatrix)
|
||||
{
|
||||
var matrix = "";
|
||||
for (var i = 0; i < rawMatrix.length; i++)
|
||||
{
|
||||
for (var j = 0; j < rawMatrix[i].length; j++)
|
||||
{
|
||||
if (i == j)
|
||||
{
|
||||
matrix += "0";
|
||||
}
|
||||
else if ((new Graph()).infinity == rawMatrix[i][j])
|
||||
{
|
||||
matrix += '\u221E';
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix += rawMatrix[i][j];
|
||||
}
|
||||
|
||||
if (j != rawMatrix[i].length - 1)
|
||||
{
|
||||
matrix += ", ";
|
||||
}
|
||||
|
||||
}
|
||||
matrix = matrix + "\n";
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
ShowDistanceMatrix.prototype.show = function()
|
||||
{
|
||||
var handler = this;
|
||||
var dialogButtons = {};
|
||||
|
||||
dialogButtons[g_close] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
var handler = g_Algorithms[g_AlgorithmIds.indexOf("OlegSh.FloidAlgorithm")](this.app.graph, this.app);
|
||||
|
||||
$( "#FloidMatrixField" ).val(this.GetIncidenceMatrix(handler.resultMatrix()));
|
||||
|
||||
$( "#floidMatrix" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_minDistMatrixText,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
}
|
61
script/features/show_incidence_matrix/index.js
Normal file
61
script/features/show_incidence_matrix/index.js
Normal file
@ -0,0 +1,61 @@
|
||||
doInclude ([
|
||||
include ("features/base_handler/index.js")
|
||||
])
|
||||
|
||||
/**
|
||||
* Save/Load graph from Incidence matrix.
|
||||
*
|
||||
*/
|
||||
function ShowIncidenceMatrix(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
// inheritance.
|
||||
ShowIncidenceMatrix.prototype = Object.create(BaseHandler.prototype);
|
||||
// First selected.
|
||||
ShowIncidenceMatrix.prototype.firstObject = null;
|
||||
// Path
|
||||
ShowIncidenceMatrix.prototype.pathObjects = null;
|
||||
|
||||
ShowIncidenceMatrix.prototype.show = function()
|
||||
{
|
||||
var handler = this;
|
||||
var dialogButtons = {};
|
||||
|
||||
$('#IncidenceMatrixField').unbind();
|
||||
$( "#IncidenceMatrixField" ).on('keyup change', function (eventObject)
|
||||
{
|
||||
if (!handler.app.TestIncidenceMatrix($( "#IncidenceMatrixField" ).val(), [], []))
|
||||
{
|
||||
$( "#BadIncidenceMatrixFormatMessage" ).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$( "#BadIncidenceMatrixFormatMessage" ).hide();
|
||||
}
|
||||
});
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
handler.app.PushToStack("IncidenceMatrixChanged");
|
||||
handler.app.SetIncidenceMatrixSmart($( "#IncidenceMatrixField" ).val());
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
dialogButtons[g_cancel] = function() {
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
$( "#IncidenceMatrixField" ).val(this.app.GetIncidenceMatrix());
|
||||
$( "#BadIncidenceMatrixFormatMessage" ).hide();
|
||||
|
||||
$( "#incidenceMatrix" ).dialog({
|
||||
resizable: false,
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
modal: true,
|
||||
title: g_incidenceMatrixText,
|
||||
buttons: dialogButtons,
|
||||
dialogClass: 'EdgeDialog'
|
||||
});
|
||||
}
|
@ -1,34 +1,18 @@
|
||||
<h1>Update cache</h1>
|
||||
|
||||
<?php
|
||||
$outputFilename = 'example.js';
|
||||
|
||||
unlink($outputFilename);
|
||||
|
||||
file_put_contents($outputFilename, file_get_contents("utils.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("texts.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("point.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("EdgeModel.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("VertexModel.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("BaseVertex.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("BaseEdge.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("BaseVertexDrawer.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("BaseEdgeDrawer.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("BaseBackgroundDrawer.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("Algorithms.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("EventHandlers.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("GraphMLCreator.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("Graph.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("EnumVertices.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("Application.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("main.js"), FILE_APPEND);
|
||||
file_put_contents($outputFilename, file_get_contents("BaseTraversal.js"), FILE_APPEND);
|
||||
|
||||
if (file_exists($outputFilename))
|
||||
{
|
||||
echo ("File exists");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo ("File not exists");
|
||||
}
|
||||
$cacheList = array(
|
||||
"/script/pages/editor/api/index.js",
|
||||
"/script/pages/create_graph_by_edge_list/api/index.js",
|
||||
"/script/pages/create_graph_by_incidence_matrix/api/index.js",
|
||||
"/script/pages/create_graph_by_matrix/api/index.js"
|
||||
);
|
||||
|
||||
echo ("<ul>");
|
||||
foreach ($cacheList as &$page) {
|
||||
$date = date('d.m.Y H:i:s', filemtime("../$page.cache"));
|
||||
echo ("<li><a href='pack.php?target=$page' target='_blank'>$page</a> $date</li>");
|
||||
}
|
||||
echo ("</ul>");
|
||||
?>
|
||||
|
||||
|
104
script/pack.php
Normal file
104
script/pack.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php if (!isset($_GET["cacheFiles"]) && isset($_GET["target"])): ?>
|
||||
<head>
|
||||
<script src="/script/shared/config.js" ></script>
|
||||
<script src="/script/shared/loader.js" ></script>
|
||||
<script src="<?= $_GET["target"] ?>" ></script>
|
||||
<script>
|
||||
setTimeout(
|
||||
() => {
|
||||
document.getElementById("state").innerHTML = "Saving files";
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "<?= $_SERVER['PHP_SELF'] ?>?cacheFiles=" + moduleLoader.syncLoaded.toString() + "&target=" + "<?= $_GET["target"] ?>");
|
||||
xhr.send();
|
||||
xhr.onload = () => {
|
||||
if (xhr.readyState == 4 && xhr.status == 200) {
|
||||
document.getElementById("state").innerHTML = "Finished <br>" + xhr.response;
|
||||
} else {
|
||||
document.getElementById("state").innerHTML = "Error happends";
|
||||
}
|
||||
};
|
||||
}, 3000);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<p>State:</p>
|
||||
<p id="state">Loading</p>
|
||||
</div>
|
||||
</doby>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
if (!isset($_GET["target"])) {
|
||||
echo ("Error target is not set");
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- Create cache file -->
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Return relative path between two sources
|
||||
* @param $from
|
||||
* @param $to
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
function relativePath($from, $to, $separator = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
$from = str_replace(array('/', '\\'), $separator, $from);
|
||||
$to = str_replace(array('/', '\\'), $separator, $to);
|
||||
|
||||
$arFrom = explode($separator, rtrim($from, $separator));
|
||||
$arTo = explode($separator, rtrim($to, $separator));
|
||||
while(count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0]))
|
||||
{
|
||||
array_shift($arFrom);
|
||||
array_shift($arTo);
|
||||
}
|
||||
|
||||
return str_pad("", count($arFrom) * 3, '..'.$separator).implode($separator, $arTo);
|
||||
}
|
||||
|
||||
include (relativePath(dirname($_SERVER['PHP_SELF']), "/") . "lib/ExtraPacker/Lib/JSMin.php");
|
||||
|
||||
if (isset($_GET["cacheFiles"])) {
|
||||
|
||||
$cacheFilenameList = $_GET["cacheFiles"];
|
||||
$files = explode(",", $cacheFilenameList);
|
||||
//print_r($files);
|
||||
$indexFilename = "../" . $_GET["target"];
|
||||
$outputFilename = $indexFilename . '.cache';
|
||||
unlink($outputFilename);
|
||||
|
||||
// Put files already loaded.
|
||||
$cacheContent = "";
|
||||
$cacheContent = $cacheContent . "\nmoduleLoader.beginCacheLoading([";
|
||||
|
||||
foreach ($files as &$file) {
|
||||
$cacheContent = $cacheContent . "\"" . $file . "\"" . ",";
|
||||
}
|
||||
$cacheContent = $cacheContent . "]);\n";
|
||||
// Put index file.
|
||||
$processedFilesCount = 1;
|
||||
$cacheContent = $cacheContent . file_get_contents($indexFilename);
|
||||
// Put files
|
||||
foreach ($files as &$file) {
|
||||
$relativePath = strtok($file, '?');
|
||||
$relativePath = relativePath(dirname($_SERVER['PHP_SELF']), $relativePath);
|
||||
$cacheContent = $cacheContent . file_get_contents($relativePath);
|
||||
$processedFilesCount ++;
|
||||
}
|
||||
// Put event about cache loaded.
|
||||
$cacheContent = $cacheContent . "\nmoduleLoader.endCacheLoading();";
|
||||
|
||||
$minifiedCacheContent = JSMin::minify($cacheContent);
|
||||
|
||||
file_put_contents($outputFilename, $minifiedCacheContent, FILE_APPEND);
|
||||
|
||||
echo("Prcoessed files: " . $processedFilesCount);
|
||||
}
|
||||
?>
|
9
script/pages/create_graph_by_edge_list/api/index.js
Normal file
9
script/pages/create_graph_by_edge_list/api/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
// Global version needs to force reload scripts from server.
|
||||
globalVersion = 75;
|
||||
|
||||
{
|
||||
let modulDir = "pages/create_graph_by_edge_list/";
|
||||
|
||||
doInclude ([
|
||||
include ("entities/graph/api/index.js")]);
|
||||
}
|
594
script/pages/create_graph_by_edge_list/api/index.js.cache
Normal file
594
script/pages/create_graph_by_edge_list/api/index.js.cache
Normal file
@ -0,0 +1,594 @@
|
||||
moduleLoader.beginCacheLoading(["/script/entities/graph/api/index.js?v=75","/script/shared/point.js?v=75","/script/entities/edge/api/index.js?v=75","/script/entities/edge/model/BaseEdge.js?v=75","/script/entities/edge/model/EdgeModel.js?v=75","/script/entities/vertex/api/index.js?v=75","/script/entities/vertex/model/BaseVertex.js?v=75","/script/entities/vertex/model/VertexModel.js?v=75","/script/entities/graph/model/Graph.js?v=75",]);globalVersion=75;{let modulDir="pages/create_graph_by_edge_list/";doInclude([include("entities/graph/api/index.js")]);}
|
||||
{let modulDir="entities/graph/";doInclude([include("shared/point.js"),include("entities/edge/api/index.js"),include("entities/vertex/api/index.js"),include("model/Graph.js",modulDir)])}function Point(x,y){this.x=x||0;this.y=y||0;};Point.prototype.x=null;Point.prototype.y=null;Point.prototype.add=function(v){return new Point(this.x+v.x,this.y+v.y);};Point.prototype.addValue=function(v){return new Point(this.x+v,this.y+v);};Point.prototype.clone=function(){return new Point(this.x,this.y);};Point.prototype.degreesTo=function(v){var dx=this.x-v.x;var dy=this.y-v.y;var angle=Math.atan2(dy,dx);return angle*(180/Math.PI);};Point.prototype.distance=function(v){return Math.sqrt(this.distanceSqr(v));};Point.prototype.distanceSqr=function(v){var x=this.x-v.x;var y=this.y-v.y;return x*x+y*y;};Point.prototype.equals=function(toCompare){return this.x==toCompare.x&&this.y==toCompare.y;};Point.prototype.interpolate=function(v,f){return new Point((this.x+v.x)*f,(this.y+v.y)*f);};Point.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};Point.prototype.normalize=function(thickness){var l=this.length();this.x=this.x/l*thickness;this.y=this.y/l*thickness;return new Point(this.x,this.y);};Point.prototype.normalizeCopy=function(thickness){var l=this.length();return new Point(this.x/l*thickness,this.y/l*thickness);};Point.prototype.orbit=function(origin,arcWidth,arcHeight,degrees){var radians=degrees*(Math.PI/180);this.x=origin.x+arcWidth*Math.cos(radians);this.y=origin.y+arcHeight*Math.sin(radians);};Point.prototype.rotate=function(center,degrees){var radians=degrees*(Math.PI/180);offset=this.subtract(center);this.x=offset.x*Math.cos(radians)-offset.y*Math.sin(radians);this.y=offset.x*Math.sin(radians)+offset.y*Math.cos(radians);this.x=this.x+center.x;this.y=this.y+center.y;return this;};Point.prototype.offset=function(dx,dy){this.x+=dx;this.y+=dy;};Point.prototype.subtract=function(v){return new Point(this.x-v.x,this.y-v.y);};Point.prototype.subtractValue=function(value){return new Point(this.x-value,this.y-value);};Point.prototype.multiply=function(value){return new Point(this.x*value,this.y*value);};Point.prototype.toString=function(){return"(x="+this.x+", y="+this.y+")";};Point.prototype.normal=function(){return new Point(-this.y,this.x);};Point.prototype.min=function(point)
|
||||
{return new Point(Math.min(this.x,point.x),Math.min(this.y,point.y));};Point.prototype.max=function(point)
|
||||
{return new Point(Math.max(this.x,point.x),Math.max(this.y,point.y));};Point.prototype.inverse=function()
|
||||
{return new Point(-this.x,-this.y);};Point.prototype.cross=function(point)
|
||||
{return this.x*point.y-this.y*point.x;};Point.interpolate=function(pt1,pt2,f){return new Point(pt1.x*(1.0-f)+pt2.x*f,pt1.y*(1.0-f)+pt2.y*f);};Point.polar=function(len,angle){return new Point(len*Math.cos(angle),len*Math.sin(angle));};Point.distance=function(pt1,pt2){var x=pt1.x-pt2.x;var y=pt1.y-pt2.y;return Math.sqrt(x*x+y*y);};Point.center=function(pt1,pt2){return new Point((pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0);};Point.toString=function(){return x+" "+y;}
|
||||
Point.projection=function(point,line1,line2)
|
||||
{var x=line2.y-line1.y;var y=line1.x-line2.x;var l=(line1.cross(line2)+line1.cross(point)+line2.cross(point))/(x*(line2.y-line1.y)+y*(line1.x-line2.x));var res=new Point(point.x+x*l,point.y+y*l);return res;}
|
||||
Point.hitTest=function(pt11,pt12,pt21,pt22)
|
||||
{var res=null;var n=0.0;var x1=pt11.x;var y1=pt11.y;var x2=pt12.x;var y2=pt12.y;var x3=pt21.x;var y3=pt21.y;var x4=pt22.x;var y4=pt22.y;if(y2-y1!=0.0)
|
||||
{var q=(x2-x1)/(y1-y2);var sn=(x3-x4)+(y3-y4)*q;if(sn==0.0)
|
||||
{return res;}
|
||||
var fn=(x3-x1)+(y3-y1)*q;n=fn/sn;}
|
||||
else
|
||||
{if((y3-y4)==0.0)
|
||||
{return res;}
|
||||
n=(y3-y1)/(y3-y4);}
|
||||
res=new Point(x3+(x4-x3)*n,y3+(y4-y3)*n);var epsilon=1E-5;if(!(res.x>=Math.min(x1,x2)-epsilon&&res.x>=Math.min(x3,x4)-epsilon&&res.x<=Math.max(x1,x2)+epsilon&&res.x<=Math.max(x3,x4)+epsilon&&res.y>=Math.min(y1,y2)-epsilon&&res.y>=Math.min(y3,y4)-epsilon&&res.y<=Math.max(y1,y2)+epsilon&&res.y<=Math.max(y3,y4)+epsilon))
|
||||
{res=null;}
|
||||
return res;}
|
||||
function Rect(minPoint,maxPoint){this.minPoint=minPoint;this.maxPoint=maxPoint;};Rect.prototype.center=function()
|
||||
{return Point.center(this.minPoint,this.maxPoint);};Rect.prototype.size=function()
|
||||
{return this.maxPoint.subtract(this.minPoint);};Rect.prototype.left=function()
|
||||
{return this.minPoint.x;};Rect.prototype.top=function()
|
||||
{return this.minPoint.y;};Rect.prototype.isIn=function(v)
|
||||
{return this.minPoint.x<=v.x&&this.minPoint.y<=v.y&&this.maxPoint.x>v.x&&this.maxPoint.y>v.y;};{let modulDir="entities/edge/";doInclude([include("model/BaseEdge.js",modulDir),include("model/EdgeModel.js",modulDir)])}
|
||||
function BaseEdge(vertex1,vertex2,isDirect,weight,upText)
|
||||
{this.vertex1=vertex1;this.vertex2=vertex2;this.arrayStyleStart="";this.arrayStyleFinish="";this.isDirect=isDirect;this.weight=0;this.text="";this.useWeight=false;this.id=0;this.model=new EdgeModel();if(upText===undefined)
|
||||
this.upText="";else
|
||||
this.upText=upText;if(weight!==undefined)
|
||||
this.SetWeight(weight);this.ownStyles={};}
|
||||
BaseEdge.prototype.copyFrom=function(other)
|
||||
{this.vertex1=other.vertex1;this.vertex2=other.vertex2;this.arrayStyleStart=other.arrayStyleStart;this.arrayStyleFinish=other.arrayStyleFinish;this.isDirect=other.isDirect;this.weight=other.weight;this.text=other.text;this.useWeight=other.useWeight;this.id=other.id;this.model=new EdgeModel();this.model.copyFrom(other.model);this.upText=other.upText;this.ownStyles=FullObjectCopy(other.ownStyles);}
|
||||
BaseEdge.prototype.SaveToXML=function()
|
||||
{return"<edge "+"source=\""+this.vertex1.id+"\" "+"target=\""+this.vertex2.id+"\" "+"isDirect=\""+this.isDirect+"\" "+"weight=\""+this.weight+"\" "+"useWeight=\""+this.useWeight+"\" "+"id=\""+this.id+"\" "+"text=\""+gEncodeToHTML(this.text)+"\" "+"upText=\""+gEncodeToHTML(this.upText)+"\" "+"arrayStyleStart=\""+this.arrayStyleStart+"\" "+"arrayStyleFinish=\""+this.arrayStyleFinish+"\" "+
|
||||
((Object.keys(this.ownStyles).length>0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+
|
||||
this.model.SaveToXML()+"></edge>";}
|
||||
BaseEdge.prototype.LoadFromXML=function(xml,graph)
|
||||
{var attr=xml.attr('vertex1');if(typeof attr==='undefined')
|
||||
{attr=xml.attr('source');}
|
||||
this.vertex1=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph1'));var attr=xml.attr('vertex2');if(typeof attr==='undefined')
|
||||
{attr=xml.attr('target');}
|
||||
this.vertex2=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph2'));this.isDirect=xml.attr('isDirect')=="true";this.weight=parseFloat(xml.attr('weight'));if(isNaN(this.weight))
|
||||
{this.weight=1;}
|
||||
this.hasPair=xml.attr('hasPair')=="true";this.useWeight=xml.attr('useWeight')=="true";this.id=xml.attr('id');this.text=xml.attr("text")==null?"":gDecodeFromHTML(xml.attr("text"));this.arrayStyleStart=xml.attr("arrayStyleStart")==null?"":xml.attr("arrayStyleStart");this.arrayStyleFinish=xml.attr("arrayStyleFinish")==null?"":xml.attr("arrayStyleFinish");this.upText=xml.attr('upText');if(typeof this.upText==='undefined')
|
||||
{this.upText="";}
|
||||
else
|
||||
{this.upText=gDecodeFromHTML(this.upText);}
|
||||
var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined')
|
||||
{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave)
|
||||
{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField])
|
||||
{if(this.ownStyles[index].ShouldLoad(field))
|
||||
this.ownStyles[index][field]=parsedSave[indexField][field];}}}
|
||||
this.model.LoadFromXML(xml);}
|
||||
BaseEdge.prototype.GetPixelLength=function()
|
||||
{if(this.vertex1==this.vertex2)
|
||||
{return this.model.GetLoopSize()*2*Math.PI;}
|
||||
else
|
||||
{return Point.distance(this.vertex1.position,this.vertex2.position);}}
|
||||
BaseEdge.prototype.GetWeight=function()
|
||||
{return this.useWeight?this.weight:1;}
|
||||
BaseEdge.prototype.GetText=function()
|
||||
{return this.text.length>0?this.text:(this.useWeight?this.weight.toString():"");}
|
||||
BaseEdge.prototype.GetUpText=function()
|
||||
{return this.upText;}
|
||||
BaseEdge.prototype.GetStartEdgeStyle=function()
|
||||
{return this.arrayStyleStart;}
|
||||
BaseEdge.prototype.GetFinishEdgeStyle=function()
|
||||
{return(this.arrayStyleFinish!=""?this.arrayStyleFinish:(this.isDirect?"arrow":""));}
|
||||
BaseEdge.prototype.HitTest=function(pos)
|
||||
{var positions=this.GetEdgePositionsShift();return this.model.HitTest(positions[0],positions[1],pos);}
|
||||
BaseEdge.prototype.GetEdgePositionsShift=function()
|
||||
{return this.GetEdgePositions();}
|
||||
BaseEdge.prototype.GetEdgePositions=function()
|
||||
{var res=[];if(this.vertex1==this.vertex2)
|
||||
{res.push(this.vertex1.position);res.push(this.vertex2.position);return res;}
|
||||
var position1=this.vertex1.position;var position2=this.vertex2.position;var diameter1=this.vertex1.model.diameter+parseInt(this.vertex1.currentStyle.GetStyle({},this.vertex1).lineWidth);var diameter2=this.vertex2.model.diameter+parseInt(this.vertex2.currentStyle.GetStyle({},this.vertex2).lineWidth);var direction=position1.subtract(position2);var direction1=direction;var direction2=direction;var d1=diameter1;var d2=diameter2;if(this.model.type==EdgeModels.curve)
|
||||
{var dist=position1.distance(position2);var point1=this.model.GetCurvePoint(position1,position2,10.0/dist);direction1=position1.subtract(point1);var point2=this.model.GetCurvePoint(position1,position2,1.0-10.0/dist);direction2=position2.subtract(point2);d2=diameter2;}
|
||||
else
|
||||
{direction2=direction2.multiply(-1);}
|
||||
direction1.normalize(1.0);direction2.normalize(1.0);var vertices=[];vertices.push({vertex:this.vertex1,direction:direction1,position:position1,diameter:d1});vertices.push({vertex:this.vertex2,direction:direction2,position:position2,diameter:d2});vertices.forEach(function(data)
|
||||
{var shape=data.vertex.currentStyle.GetStyle({},data.vertex).shape;if(shape==VertexCircleShape)
|
||||
{var direction=data.direction.multiply(0.5);res.push(data.position.subtract(direction.multiply(data.diameter)));}
|
||||
else
|
||||
{var lineFinish1=data.direction.multiply(-1).multiply(1000.0);var pointsVertex1=GetPointsForShape(shape,data.diameter,data.vertex.mainText);pointsVertex1.push(pointsVertex1[0]);for(var i=0;i<pointsVertex1.length-1;i++)
|
||||
{var hitText=Point.hitTest(new Point(0,0),lineFinish1,pointsVertex1[i],pointsVertex1[i+1]);if(hitText!=null)
|
||||
{res.push(data.position.add(hitText));break;}}}});return res;}
|
||||
BaseEdge.prototype.SetWeight=function(weight)
|
||||
{var useWeight=false;if(!isNaN(parseInt(weight,10)))
|
||||
{useWeight=true;}
|
||||
weight=(!isNaN(parseInt(weight,10))&&weight>=0)?weight:1;this.weight=Number(weight);this.useWeight=useWeight;}
|
||||
BaseEdge.prototype.SetUpText=function(text)
|
||||
{this.upText=text;}
|
||||
BaseEdge.prototype.resetOwnStyle=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{delete this.ownStyles[index];}}
|
||||
BaseEdge.prototype.setOwnStyle=function(index,style)
|
||||
{this.ownStyles[index]=style;}
|
||||
BaseEdge.prototype.getStyleFor=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{return this.ownStyles[index];}
|
||||
else
|
||||
{var style=null;if(index==0)
|
||||
style=globalApplication.GetStyle("edge","common");else
|
||||
style=globalApplication.GetStyle("edge","selected",undefined,index-1);return style;}}
|
||||
BaseEdge.prototype.hasOwnStyleFor=function(index)
|
||||
{return this.ownStyles.hasOwnProperty(index);}
|
||||
var EdgeModels={"line":0,"curve":1};const defaultEdgeWidth=4;function EdgeModel()
|
||||
{this.width=globalApplication.GetDefaultEdgeWidth();this.type=EdgeModels.line;this.curveValue=EdgeModel.prototype.defaultCurve;this.default=true;this.sizeOfLoop=24;this.loopShiftAngel=Math.PI/6;}
|
||||
EdgeModel.prototype.defaultCurve=0.1;EdgeModel.prototype.copyFrom=function(other)
|
||||
{this.width=other.width;this.type=other.type;this.curveValue=other.curveValue;this.default=other.default;}
|
||||
EdgeModel.prototype.SaveToXML=function()
|
||||
{return"model_width=\""+this.width+"\" "+"model_type=\""+this.type+"\" "+"model_curveValue=\""+this.curveValue+"\" "+"model_default=\""+this.default+"\" ";}
|
||||
EdgeModel.prototype.LoadFromXML=function(xml,graph)
|
||||
{this.width=xml.attr('model_width')==null?this.width:parseFloat(xml.attr("model_width"));this.type=xml.attr('model_type')==null?this.type:xml.attr("model_type");this.curveValue=xml.attr('model_curveValue')==null?this.curveValue:parseFloat(xml.attr("model_curveValue"));this.default=xml.attr('model_default')==null?this.default:parseFloat(xml.attr("model_default"));}
|
||||
EdgeModel.prototype.GetCurvePoint=function(position1,position2,t)
|
||||
{var points=this.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];var B0_t=Math.pow(1-t,3);var B1_t=3*t*Math.pow(1-t,2);var B2_t=3*t*t*(1-t)
|
||||
var B3_t=t*t*t;var ax=position1.x;var ay=position1.y;var dx=position2.x;var dy=position2.y;var bx=firstBezierPoint.x;var by=firstBezierPoint.y;var cx=secondBezierPoint.x;var cy=secondBezierPoint.y;var px_t=(B0_t*ax)+(B1_t*bx)+(B2_t*cx)+(B3_t*dx);var py_t=(B0_t*ay)+(B1_t*by)+(B2_t*cy)+(B3_t*dy);return new Point(px_t,py_t);}
|
||||
EdgeModel.prototype.GetBezierPoints=function(position1,position2)
|
||||
{var direction=position2.subtract(position1);var delta=direction.length();direction.normalize(1.0);var normal=direction.normal();var deltaOffsetPixels=delta*this.curveValue;var yOffset=normal.multiply(deltaOffsetPixels);var firstBezierPointShift=(direction.multiply(delta*0.2)).add(yOffset);var secondBezierPointShift=(direction.multiply(-delta*0.2)).add(yOffset);var firstBezierPoint=position1.add(firstBezierPointShift);var secondBezierPoint=position2.add(secondBezierPointShift);return[firstBezierPoint,secondBezierPoint];}
|
||||
EdgeModel.prototype.HitTest=function(position1,position2,mousePos)
|
||||
{if(this.type==EdgeModels.line)
|
||||
return this.HitTestLine(position1,position2,mousePos);else if(this.type==EdgeModels.curve)
|
||||
return this.HitTestCurve(position1,position2,mousePos);return false;}
|
||||
EdgeModel.prototype.HitTestLine=function(position1,position2,mousePos,factor)
|
||||
{if(factor===undefined)
|
||||
{factor=1.0;}
|
||||
var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2))
|
||||
{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5*factor;}
|
||||
var r1=pos0.distance(pos1);var r2=pos0.distance(pos2);var r12=pos1.distance(pos2);if(r1>=(new Point(r2,r12)).length()||r2>=(new Point(r1,r12)).length())
|
||||
{}
|
||||
else
|
||||
{var distance=((pos1.y-pos2.y)*pos0.x+(pos2.x-pos1.x)*pos0.y+(pos1.x*pos2.y-pos2.x*pos1.y))/r12;if(Math.abs(distance)<=this.width*1.5*factor)
|
||||
{return true;}}
|
||||
return false;}
|
||||
EdgeModel.prototype.HitTestCurve=function(position1,position2,mousePos)
|
||||
{var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2))
|
||||
{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5;}
|
||||
var interval_count=position1.distance(position2)/100*30;var start=position1;for(var i=0;i<interval_count;i++)
|
||||
{var finish=this.GetCurvePoint(position1,position2,i/interval_count);if(this.HitTestLine(start,finish,mousePos,2.0))
|
||||
return true;start=finish;}
|
||||
return false;}
|
||||
EdgeModel.prototype.ChangeCurveValue=function(delta)
|
||||
{if(this.type==EdgeModels.line)
|
||||
{this.type=EdgeModels.curve;this.curveValue=0.0;}
|
||||
this.curveValue=this.curveValue+delta;if(Math.abs(this.curveValue)<=0.01)
|
||||
this.type=EdgeModels.line;this.default=false;}
|
||||
EdgeModel.prototype.SetCurveValue=function(value)
|
||||
{if(this.type==EdgeModels.line)
|
||||
{this.type=EdgeModels.curve;this.curveValue=0.0;}
|
||||
this.curveValue=value;if(Math.abs(this.curveValue)<=0.01)
|
||||
this.type=EdgeModels.line;this.default=false;}
|
||||
EdgeModel.prototype.GetLoopSize=function()
|
||||
{if(Math.abs(this.curveValue)<=0.01)
|
||||
{return this.sizeOfLoop;}
|
||||
else
|
||||
{let normalCurve=this.curveValue;if(this.type==EdgeModels.line){normalCurve=this.defaultCurve;}
|
||||
else if(normalCurve>=0.0){normalCurve+=this.defaultCurve}
|
||||
return this.sizeOfLoop*Math.abs(normalCurve)*(1/this.defaultCurve);}}
|
||||
EdgeModel.prototype.GetLoopShiftAngel=function()
|
||||
{if(this.type==EdgeModels.line||this.curveValue>=0.0)
|
||||
{return this.loopShiftAngel;}
|
||||
else
|
||||
{return this.loopShiftAngel+Math.PI;}}
|
||||
{let modulDir="entities/vertex/";doInclude([include("model/BaseVertex.js",modulDir),include("model/VertexModel.js",modulDir)])}
|
||||
function BaseVertex(x,y,vertexEnumType)
|
||||
{this.position=new Point(x,y);this.id=0;this.mainText="";this.upText="";this.vertexEnumType=vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=false;this.ownStyles={};};BaseVertex.prototype.position=new Point(0,0);BaseVertex.prototype.copyFrom=function(other)
|
||||
{this.position=new Point(other.position.x,other.position.y);this.id=other.id;this.mainText=other.mainText;this.upText=other.upText;this.vertexEnumType=other.vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=other.hasUndefinedPosition;this.ownStyles=FullObjectCopy(other.ownStyles);}
|
||||
BaseVertex.prototype.SaveToXML=function()
|
||||
{return"<node "+"positionX=\""+this.position.x+"\" "+"positionY=\""+this.position.y+"\" "+"id=\""+this.id+"\" "+"mainText=\""+gEncodeToHTML(this.mainText)+"\" "+"upText=\""+gEncodeToHTML(this.upText)+"\" "+
|
||||
((Object.keys(this.ownStyles).length>0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+"size=\""+this.model.diameter+"\" "+"></node>";}
|
||||
BaseVertex.prototype.LoadFromXML=function(xml)
|
||||
{var xmlX=xml.attr('positionX');var xmlY=xml.attr('positionY');this.hasUndefinedPosition=(typeof xmlX==='undefined')||(typeof xmlY==='undefined');this.position=new Point(parseFloat(xmlX),parseFloat(xmlY));this.id=xml.attr('id');this.mainText=xml.attr('mainText');this.upText=xml.attr('upText');if(typeof this.mainText==='undefined')
|
||||
this.mainText=this.id;else
|
||||
this.mainText=gDecodeFromHTML(this.mainText);if(typeof this.upText==='undefined')
|
||||
this.upText="";else
|
||||
this.upText=gDecodeFromHTML(this.upText);var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined')
|
||||
{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave)
|
||||
{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField])
|
||||
{if(this.ownStyles[index].ShouldLoad(field))
|
||||
this.ownStyles[index][field]=parsedSave[indexField][field];}}}
|
||||
var size=xml.attr('size');if(typeof size!=='undefined')
|
||||
this.model.diameter=parseInt(size);}
|
||||
BaseVertex.prototype.SetId=function(id)
|
||||
{this.id=id;if(this.vertexEnumType!=null)
|
||||
this.mainText=this.vertexEnumType.GetVertexText(id);}
|
||||
BaseVertex.prototype.diameterFactor=function()
|
||||
{return new Point(1.0+(this.mainText.length?this.mainText.length/8.0:0),1.5);}
|
||||
BaseVertex.prototype.IsUndefinedPosition=function()
|
||||
{return this.hasUndefinedPosition;}
|
||||
BaseVertex.prototype.HitTest=function(pos)
|
||||
{var shape=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).shape:VertexCircleShape;var width=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).lineWidth:0;if(shape==VertexCircleShape)
|
||||
{return this.position.distance(pos)<this.model.diameter/2.0+width;}
|
||||
else
|
||||
{var relativePos=(new Point(pos.x,pos.y)).subtract(this.position);var lineFinish1=relativePos.add(new Point(1000,0));var lineFinish2=relativePos.add(new Point(-1000,0));var pointsVertex1=GetPointsForShape(shape,this.model.diameter+width,this.mainText);pointsVertex1.push(pointsVertex1[0]);var hitNumber1=0;var hitNumber2=0;for(var i=0;i<pointsVertex1.length-1;i++)
|
||||
{var hitTest=Point.hitTest(relativePos,lineFinish1,pointsVertex1[i],pointsVertex1[i+1]);if(hitTest!=null)
|
||||
{hitNumber1++;}
|
||||
hitTest=Point.hitTest(relativePos,lineFinish2,pointsVertex1[i],pointsVertex1[i+1]);if(hitTest!=null)
|
||||
{hitNumber2++;}}
|
||||
return hitNumber1==1&&hitNumber2==1;}
|
||||
return false;}
|
||||
BaseVertex.prototype.resetOwnStyle=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{delete this.ownStyles[index];}}
|
||||
BaseVertex.prototype.setOwnStyle=function(index,style)
|
||||
{this.ownStyles[index]=FullObjectCopy(style);}
|
||||
BaseVertex.prototype.getStyleFor=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{return this.ownStyles[index];}
|
||||
else
|
||||
{var style=null;if(index==0)
|
||||
style=globalApplication.GetStyle("vertex","common");else
|
||||
style=globalApplication.GetStyle("vertex","selected",undefined,index-1);return style;}}
|
||||
BaseVertex.prototype.hasOwnStyleFor=function(index)
|
||||
{return this.ownStyles.hasOwnProperty(index);}
|
||||
const defaultVertexDiameter=30;function VertexModel()
|
||||
{this.diameter=globalApplication.GetDefaultVertexSize();}
|
||||
function Graph()
|
||||
{this.vertices=[];this.edges=[];this.uidGraph=0;this.uidEdge=10000;this.hasDirect=false;this.isMultiGraph=false;};Graph.prototype.infinity=1E8;Graph.prototype.maxVertices=1000;Graph.prototype.edgesOffset=10000;Graph.prototype.AddNewVertex=function(vertex)
|
||||
{if(this.vertices.length<=this.maxVertices)
|
||||
{vertex.SetId(this.uidGraph);this.uidGraph=this.uidGraph+1;this.vertices.push(vertex);}
|
||||
return this.vertices.length-1;}
|
||||
Graph.prototype.ClearGraph=function(){this.vertices=[];this.edges=[];this.uidGraph=0;this.uidEdge=10000;this.hasDirect=false;this.isMultiGraph=false;}
|
||||
Graph.prototype.AddNewEdgeSafe=function(graph1,graph2,isDirect,weight,replaceIfExists=true)
|
||||
{return this.AddNewEdge(new BaseEdge(graph1,graph2,isDirect,weight),replaceIfExists);}
|
||||
Graph.prototype.AddNewEdge=function(edge,replaceIfExists)
|
||||
{edge.id=this.uidEdge;this.uidEdge=this.uidEdge+1;var edge1=this.FindEdgeAny(edge.vertex1.id,edge.vertex2.id);var edgeRevert=this.FindEdgeAny(edge.vertex2.id,edge.vertex1.id);if(!edge.isDirect)
|
||||
{if(edge1!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edge1);if(edgeRevert!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edgeRevert);this.edges.push(edge);}
|
||||
else
|
||||
{if(edge1!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edge1);if(edgeRevert!=null&&!edgeRevert.isDirect&&replaceIfExists)
|
||||
this.DeleteEdge(edgeRevert);this.edges.push(edge);}
|
||||
this.isMultiGraph=this.checkMutiGraph();return this.edges.length-1;}
|
||||
Graph.prototype.DeleteEdge=function(edgeObject)
|
||||
{var index=this.edges.indexOf(edgeObject);if(index>-1)
|
||||
{this.edges.splice(index,1);}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.DeleteVertex=function(vertexObject)
|
||||
{var index=this.vertices.indexOf(vertexObject);if(index>-1)
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].vertex1==vertexObject||this.edges[i].vertex2==vertexObject)
|
||||
{this.DeleteEdge(this.edges[i]);i--;}}
|
||||
this.vertices.splice(index,1);}}
|
||||
Graph.prototype.HasConnectedNodes=function(vertexObject)
|
||||
{var res=false;var index=this.vertices.indexOf(vertexObject);if(index>-1)
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].vertex1==vertexObject||this.edges[i].vertex2==vertexObject)
|
||||
{res=true;break;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindVertex=function(id)
|
||||
{var res=null;for(var i=0;i<this.vertices.length;i++)
|
||||
{if(this.vertices[i].id==id)
|
||||
{res=this.vertices[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindVertexByTitle=function(title)
|
||||
{var res=null;for(var i=0;i<this.vertices.length;i++)
|
||||
{if(this.vertices[i].mainText==title)
|
||||
{res=this.vertices[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdge=function(id1,id2)
|
||||
{return this.FindEdgeAny(id1,id2);}
|
||||
Graph.prototype.FindEdgeById=function(edgeId)
|
||||
{var res=null;for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].id==edgeId)
|
||||
{res=this.edges[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeAny=function(id1,id2)
|
||||
{var res=null;for(var i=0;i<this.edges.length;i++)
|
||||
{if((this.edges[i].vertex1.id==id1&&this.edges[i].vertex2.id==id2)||(!this.edges[i].isDirect&&this.edges[i].vertex1.id==id2&&this.edges[i].vertex2.id==id1))
|
||||
{res=this.edges[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMin=function(id1,id2)
|
||||
{var res=null;var minWeight=this.infinity;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight<minWeight)
|
||||
{res=edge;minWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMax=function(id1,id2)
|
||||
{var res=null;var maxWeight=0;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight>maxWeight)
|
||||
{res=edge;maxWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMinIgnoreDirection=function(id1,id2)
|
||||
{var res=null;var minWeight=this.infinity;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight<minWeight)
|
||||
{res=edge;minWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindAllEdges=function(id1,id2)
|
||||
{var res=[];for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{res.push(edge);}}
|
||||
return res;}
|
||||
Graph.prototype.GetAdjacencyMatrixStr=function()
|
||||
{var matrix="";for(var i=0;i<this.vertices.length;i++)
|
||||
{for(var j=0;j<this.vertices.length;j++)
|
||||
{var edge=this.FindEdgeMin(this.vertices[i].id,this.vertices[j].id);if(edge!=null)
|
||||
{matrix+=edge.weight;}
|
||||
else
|
||||
{matrix+="0";}
|
||||
if(j!=this.vertices.length)
|
||||
{matrix+=", ";}}
|
||||
matrix=matrix+"\n";}
|
||||
return matrix;}
|
||||
Graph.prototype.GetAdjacencyMatrix=function()
|
||||
{var matrix=[];for(var i=0;i<this.vertices.length;i++)
|
||||
{matrix.push([]);var v1=this.vertices[i];for(var j=0;j<this.vertices.length;j++)
|
||||
{var v2=this.vertices[j];var edge=this.FindEdgeMin(v1.id,v2.id);if(edge!=null)
|
||||
{matrix[i][j]=edge.GetWeight();}
|
||||
else
|
||||
{matrix[i][j]=this.infinity;}}}
|
||||
return matrix;}
|
||||
Graph.prototype.TestAdjacencyMatrix=function(matrix,rowsObj,colsObj,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j<rowsObj.rows.length;++j)
|
||||
{if(rowsObj.rows[j]==="")
|
||||
{rowsObj.rows.splice(j--,1);}}
|
||||
colsObj.cols=[];for(var i=0;i<rowsObj.rows.length;i++)
|
||||
{colsObj.cols[i]=this.SplitMatrixString(rowsObj.rows[i],separator);for(j=0;j<colsObj.cols[i].length;++j)
|
||||
{if(colsObj.cols[i][j]==="")
|
||||
{colsObj.cols[i].splice(j--,1);}}
|
||||
if(colsObj.cols[i].length!=rowsObj.rows.length)
|
||||
{bGoodFormat=false;break;}}
|
||||
return bGoodFormat;}
|
||||
Graph.prototype.TestPair=function(pair)
|
||||
{let lines=pair.split("\n");let regExp=[/^.+-.+$/g,/^.+\>.+$/g,/^.+<.+$/g,/^.+-\(\d+\.?\d+\)-.+$/g,/^.+-\(\d+\.?\d+\)\>.+$/g,/^.+<\(\d+\.?\d+\)\-.+$/g];let res=true;for(let i=0;i<lines.length;++i)
|
||||
{let resLine=false;let line=lines[i];if(line==""){continue;}
|
||||
for(let j=0;j<regExp.length;++j){if(line.match(regExp[j])){resLine=true;}}
|
||||
res=resLine&&res;}
|
||||
return res;}
|
||||
Graph.prototype.IsVerticesHaveSamePosition=function(position,vertexCount)
|
||||
{var res=false;for(var j=0;j<Math.min(this.vertices.length,vertexCount);j++)
|
||||
{if(position.distance(this.vertices[j].position)<this.vertices[j].model.diameter*2)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.GetRandomPosition=function(viewportSize){return new Point(Math.random()*viewportSize.x,Math.random()*viewportSize.y);}
|
||||
Graph.prototype.GetRandomPositionOfVertex=function(matrix,vertexIndex,viewportSize)
|
||||
{var point=new Point(0,0);var relatedVertex=[];for(var j=0;j<matrix.length;j++)
|
||||
{if(j<this.vertices.length&&(cols[vertexIndex][j]>0||cols[j][vertexIndex]>0)&&j!=vertexIndex)
|
||||
{relatedVertex.push(this.vertices[j]);}}
|
||||
var diameter=(new VertexModel()).diameter;if(relatedVertex.length>1)
|
||||
{for(var j=0;j<relatedVertex.length;j++)
|
||||
{point=point.add(relatedVertex[j].position);}
|
||||
point=point.multiply(1/relatedVertex.length);point.offset(Math.random()*diameter+(Math.random()?-1:1)*2*diameter,Math.random()*diameter+(Math.random()?-1:1)*2*diameter);}
|
||||
else
|
||||
{point=new Point(Math.random()*viewportSize.x,Math.random()*viewportSize.y);}
|
||||
if(this.IsVerticesHaveSamePosition(point,matrix.length))
|
||||
{point.offset(Math.random()*diameter+ +(Math.random()?-1:1)*4*diameter,Math.random()*diameter+ +(Math.random()?-1:1)*4*diameter);}
|
||||
point.x=Math.min(Math.max(point.x,diameter),viewportSize.x);point.y=Math.min(Math.max(point.y,diameter),viewportSize.y);return point;}
|
||||
Graph.prototype.VerticesReposition=function(viewportSize,newVertices)
|
||||
{var maxGravityDistanceSqr=Math.max(viewportSize.x,viewportSize.y)/5.0;maxGravityDistanceSqr=maxGravityDistanceSqr*maxGravityDistanceSqr;var velocityDamping=0.85;var diameter=(new VertexModel()).diameter;var maxDistance=diameter*3;var gravityDistanceSqr=10*(maxDistance*maxDistance);var edgeGravityKof=10/(maxDistance);var kCenterForce=10/(maxDistance*10);var centerPoint=viewportSize.multiply(0.5);var velocityMax=maxDistance*10;var edgesMatrix={};for(var i=0;i<this.edges.length;i++)
|
||||
{edgesMatrix[this.edges[i].vertex1.id+this.edges[i].vertex2.id*1000]=1;edgesMatrix[this.edges[i].vertex2.id+this.edges[i].vertex1.id*1000]=1;}
|
||||
var startAngel=Math.random()*180.0;for(i=0;i<newVertices.length;i++)
|
||||
{newVertices[i].position.orbit(new Point(viewportSize.x/2,viewportSize.y/2),(viewportSize.x-diameter*2)/2,(viewportSize.y-diameter*2)/2,360*i/newVertices.length+startAngel);}
|
||||
var k=0;var bChanged=true;while(k<1000&&bChanged)
|
||||
{var vertexData=[];for(i=0;i<newVertices.length;i++)
|
||||
{var currentVertex={};currentVertex.object=newVertices[i];currentVertex.net_force=new Point(0,0);currentVertex.velocity=new Point(0,0);vertexData.push(currentVertex);for(j=0;j<this.vertices.length;j++)
|
||||
{otherVertex=this.vertices[j];if(otherVertex==currentVertex.object)continue;var rsq=currentVertex.object.position.distanceSqr(otherVertex.position);{var force=(currentVertex.object.position.subtract(otherVertex.position)).normalize(gravityDistanceSqr/rsq);currentVertex.net_force=currentVertex.net_force.add(force);}}
|
||||
for(j=0;j<this.vertices.length;j++)
|
||||
{otherVertex=this.vertices[j];if(edgesMatrix.hasOwnProperty(currentVertex.object.id+1000*otherVertex.id))
|
||||
{var distance=currentVertex.object.position.distance(otherVertex.position);if(distance>maxDistance)
|
||||
{var force=(otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof*(distance-maxDistance));currentVertex.net_force=currentVertex.net_force.add(force);}}}
|
||||
var distanceToCenter=centerPoint.distance(currentVertex.object.position);var force=centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter*kCenterForce);currentVertex.net_force=currentVertex.net_force.add(force);currentVertex.velocity=currentVertex.velocity.add(currentVertex.net_force);}
|
||||
bChanged=false;for(i=0;i<vertexData.length;i++)
|
||||
{var v=vertexData[i];var velocity=v.velocity;if(velocity.length()>velocityMax)
|
||||
{velocity=velocity.normalize(velocityMax);}
|
||||
v.object.position=v.object.position.add(velocity);if(velocity.length()>=1)
|
||||
{bChanged=true;}}
|
||||
k++;}
|
||||
var bbox=this.getGraphBBox();if(bbox.size().length()>viewportSize.length()*1000)
|
||||
{for(i=0;i<newVertices.length;i++)
|
||||
{newVertices[i].position.orbit(new Point(viewportSize.x/2,viewportSize.y/2),(viewportSize.x-diameter*2)/2,(viewportSize.y-diameter*2)/2,360*i/newVertices.length+startAngel);}}
|
||||
else
|
||||
{var count=10;var angle=360.0/count;var viewportAspect=viewportSize.x/viewportSize.y;var bestIndex=0;var graphSize=bbox.size();var bestAspect=graphSize.x/graphSize.y;var center=bbox.center();for(var i=1;i<count;i++)
|
||||
{for(j=0;j<newVertices.length;j++)
|
||||
{newVertices[j].position.rotate(center,angle);}
|
||||
var newBBox=this.getGraphBBox();var newAspect=newBBox.size().x/newBBox.size().y;if(Math.abs(newAspect-viewportAspect)<Math.abs(bestAspect-viewportAspect))
|
||||
{bestAspect=newAspect;bestIndex=i;}}
|
||||
for(j=0;j<newVertices.length;j++)
|
||||
{newVertices[j].position.rotate(center,-angle*(count-bestIndex-1));}}}
|
||||
Graph.prototype.SetAdjacencyMatrix=function(matrix,viewportSize,currentEnumVerticesType,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var rowsObj={};var colsObj={};if(this.TestAdjacencyMatrix(matrix,rowsObj,colsObj,separator))
|
||||
{rows=rowsObj.rows;cols=colsObj.cols;var clonedEdge=this.edges.slice(0);for(var i=0;i<clonedEdge.length;i++)
|
||||
{this.DeleteEdge(clonedEdge[i]);}
|
||||
var newVertices=[];var bWeightGraph=false;for(var i=0;i<rows.length;i++)
|
||||
{for(var j=0;j<rows.length;j++)
|
||||
{if(j>=this.vertices.length)
|
||||
{var newPos=this.GetRandomPositionOfVertex(matrix,j,viewportSize);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);}
|
||||
if(cols[i][j]>0)
|
||||
{var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[i],this.vertices[j],cols[i][j]!=cols[j][i],cols[i][j],true);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0)
|
||||
{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
for(var i=rows.length;i<Math.max(this.vertices.length,rows.length);i++)
|
||||
{this.DeleteVertex(this.vertices[i]);i--;}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.SetPair=function(pairs,viewportSize,currentEnumVerticesType)
|
||||
{if(this.TestPair(pairs))
|
||||
{this.ClearGraph();let lines=pairs.split("\n");let regExp=[/^(.+)-(.+)$/g,/^(.+)\>(.+)$/g,/^(.+)<(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)-(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)\>(.+)$/g,/^(.+)<\((\d+|\d+\.?\d+)\)\-(.+)$/g,];let bWeightGraph=false;var newVertices=[];for(var i=0;i<lines.length;i++)
|
||||
{let line=lines[i];if(line==""){continue;}
|
||||
for(let j=regExp.length-1;j>=0;--j){if(!line.match(regExp[j])){continue;}
|
||||
let groupes=Array.from(line.matchAll(regExp[j]));let groupe=groupes[0];let vetext1Title=groupe[1];let vertex1=this.FindVertexByTitle(vetext1Title);if(vertex1==null){let newPosition=this.GetRandomPosition(viewportSize);vertex1=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex1.mainText=vetext1Title;newVertices.push(vertex1);}
|
||||
let vetext2Title=groupe[j<=2?2:3];let vertex2=this.FindVertexByTitle(vetext2Title);if(vertex2==null){let newPosition=this.GetRandomPosition(viewportSize);vertex2=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex2.mainText=vetext2Title;newVertices.push(vertex2);}
|
||||
let isDirect=j==1||j==2||j==4||j==5;let weight=1;if(j>2){weight=groupe[2];bWeightGraph=true;}
|
||||
let isRevertEdge=j==2||j==5;let nEdgeIndex=this.AddNewEdgeSafe(isRevertEdge?vertex2:vertex1,isRevertEdge?vertex1:vertex2,isDirect,weight,false);this.FixEdgeCurve(nEdgeIndex);break;}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j<rowsObj.rows.length;++j)
|
||||
{if(rowsObj.rows[j]==="")
|
||||
{rowsObj.rows.splice(j--,1);}}
|
||||
colsObj.cols=[];var columnCount=0;for(var i=0;i<rowsObj.rows.length;i++)
|
||||
{colsObj.cols[i]=this.SplitMatrixString(rowsObj.rows[i],separator);for(j=0;j<colsObj.cols[i].length;++j)
|
||||
{if(colsObj.cols[i][j]==="")
|
||||
{colsObj.cols[i].splice(j--,1);}}
|
||||
if(i==0)
|
||||
{columnCount=colsObj.cols[i].length;}
|
||||
if(colsObj.cols[i].length!=columnCount)
|
||||
{bGoodFormat=false;break;}}
|
||||
if(bGoodFormat)
|
||||
{for(var i=0;i<colsObj.cols[0].length;i++)
|
||||
{var values=[];for(j=0;j<colsObj.cols.length;++j)
|
||||
{if(colsObj.cols[j][i]!=0)
|
||||
{values.push(colsObj.cols[j][i]);}}
|
||||
if(!(values.length<=1||(values.length==2&&(values[0]==values[1]||values[0]==-values[1]))))
|
||||
{bGoodFormat=false;break;}}}
|
||||
return bGoodFormat;}
|
||||
Graph.prototype.SetIncidenceMatrix=function(matrix,viewportSize,currentEnumVerticesType)
|
||||
{var rowsObj={};var colsObj={};if(this.TestIncidenceMatrix(matrix,rowsObj,colsObj))
|
||||
{rows=rowsObj.rows;cols=colsObj.cols;var clonedEdge=this.edges.slice(0);for(var i=0;i<clonedEdge.length;i++)
|
||||
{this.DeleteEdge(clonedEdge[i]);}
|
||||
var newVertices=[];var bWeightGraph=false;for(var i=0;i<cols[0].length;i++)
|
||||
{var edgeValue=[];var edgeIndex=[];for(var j=0;j<cols.length;j++)
|
||||
{if(j>=this.vertices.length)
|
||||
{var newPos=new Point(0,0);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);}
|
||||
if(cols[j][i]!=0)
|
||||
{edgeValue.push(cols[j][i]);edgeIndex.push(j);}}
|
||||
if(edgeIndex.length==1)
|
||||
{edgeValue.push(edgeValue[0]);edgeIndex.push(edgeIndex[0]);}
|
||||
if(edgeIndex.length==2)
|
||||
{if(edgeValue[0]!=edgeValue[1])
|
||||
{if(edgeValue[1]>0)
|
||||
{edgeValue=edgeValue.swap(0,1);edgeIndex=edgeIndex.swap(0,1);}}
|
||||
var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[edgeIndex[0]],this.vertices[edgeIndex[1]],edgeValue[0]!=edgeValue[1],Math.abs(edgeValue[1]),false);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0)
|
||||
{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
for(var i=cols.length;i<Math.max(this.vertices.length,cols.length);i++)
|
||||
{this.DeleteVertex(this.vertices[i]);i--;}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.GetIncidenceMatrix=function()
|
||||
{var matrix="";for(var i=0;i<this.vertices.length;i++)
|
||||
{for(var j=0;j<this.edges.length;j++)
|
||||
{if(this.edges[j].vertex1==this.vertices[i])
|
||||
{matrix+=this.edges[j].weight;}
|
||||
else if(this.edges[j].vertex2==this.vertices[i]&&!this.edges[j].isDirect)
|
||||
{matrix+=this.edges[j].weight;}
|
||||
else if(this.edges[j].vertex2==this.vertices[i]&&this.edges[j].isDirect)
|
||||
{matrix+=-this.edges[j].weight;}
|
||||
else
|
||||
{matrix+="0";}
|
||||
if(j!=this.edges.length-1)
|
||||
{matrix+=", ";}}
|
||||
matrix=matrix+"\n";}
|
||||
return matrix;}
|
||||
Graph.prototype.SplitMatrixString=function(line,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var res=[];var i=0;var isZeroOneLine=true;for(i=0;i<line.length;i++)
|
||||
{if(line.charAt(i)!='0'&&line.charAt(i)!='1')
|
||||
{isZeroOneLine=false;break;}}
|
||||
if(!isZeroOneLine)
|
||||
{if(separator!=",")
|
||||
{line=line.replace(/,/g,".");}
|
||||
for(i=0;i<line.length;i++)
|
||||
{if(("0123456789.-e").indexOf(line.charAt(i))<0)
|
||||
{if(i>0)
|
||||
{res.push(line.substr(0,i));}
|
||||
if(i==0)
|
||||
{i=1;}
|
||||
line=line.substr(i,line.length-i);i=-1;}}
|
||||
if(line.length>0)
|
||||
{res.push(line);}}
|
||||
else
|
||||
{for(i=0;i<line.length;i++)
|
||||
{res.push(line.charAt(i));}}
|
||||
console.log(res);return res;}
|
||||
Graph.prototype.SaveToXML=function(additionalData)
|
||||
{var mainHeader="<?xml version=\"1.0\" encoding=\"UTF-8\"?><graphml>";var header="<graph id=\"Graph\" uidGraph=\""+this.uidGraph+"\""+" uidEdge=\""+this.uidEdge+"\">";var xmlBody="";for(var i=0;i<this.vertices.length;i++)
|
||||
{xmlBody=xmlBody+this.vertices[i].SaveToXML();}
|
||||
xmlBody=xmlBody+"";for(var i=0;i<this.edges.length;i++)
|
||||
{xmlBody=xmlBody+this.edges[i].SaveToXML();}
|
||||
xmlBody=xmlBody+"";additionalField="";if(additionalData.length>0)
|
||||
{additionalField="<additional data=\""+additionalData+"\"/>"}
|
||||
return mainHeader+header+xmlBody+"</graph>"+additionalField+"</graphml>";}
|
||||
Graph.prototype.LoadFromXML=function(xmlText,additionalData)
|
||||
{xmlDoc=$.parseXML(xmlText);var $xml=$(xmlDoc);$graphs=$xml.find("graph");var loadedGraphId=0;var loadedEdgeId=0;$graphs.each(function(){loadedGraphId=parseInt($(this).attr('uidGraph'));loadedEdgeId=parseInt($(this).attr('uidEdge'));});if(isNaN(loadedEdgeId))
|
||||
{loadedEdgeId=this.edgesOffset;}else if(loadedEdgeId<this.edgesOffset)
|
||||
{loadedEdgeId=this.edgesOffset;}
|
||||
this.uidGraph=loadedGraphId;this.uidEdge=loadedEdgeId;$nodes=$xml.find("node");var vertices=[];$nodes.each(function(){var vertex=new BaseVertex();vertex.LoadFromXML($(this));vertices.push(vertex);});this.vertices=vertices;$edges=$xml.find("edge");var edges=[];var graph=this;$edges.each(function(){var edge=new BaseEdge();edge.LoadFromXML($(this),graph);if(edge.id<graph.uidEdge){edge.id=graph.uidEdge;graph.uidEdge++;}
|
||||
edges.push(edge);});this.edges=edges;$additional=$xml.find("additional");if($additional.length!=0&&additionalData!=null)
|
||||
{additionalData["data"]=$additional.attr('data');}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.hasDirectEdge=function()
|
||||
{var res=false;for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.hasUndirectEdge=function()
|
||||
{var res=false;for(var i=0;i<this.edges.length;i++)
|
||||
{if(!this.edges[i].isDirect)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.hasEdges=function()
|
||||
{return this.edges.length>0;}
|
||||
Graph.prototype.clampPositions=function(viewportSize)
|
||||
{var diameter=(new VertexModel()).diameter;for(i=0;i<this.vertices.length;i++)
|
||||
{this.vertices[i].position.x=Math.min(Math.max(this.vertices[i].position.x,diameter),viewportSize.x-diameter);this.vertices[i].position.y=Math.min(Math.max(this.vertices[i].position.y,diameter),viewportSize.y-diameter);}}
|
||||
Graph.prototype.getGraphBBox=function(viewportSize)
|
||||
{var pointMin=new Point(1e5,1e5);var pointMax=new Point(-1e5,-1e5);var diameter=(new VertexModel()).diameter;for(i=0;i<this.vertices.length;i++)
|
||||
{var vertex=this.vertices[i];var factor=vertex.diameterFactor();var deltaVector=new Point(factor.x*diameter,factor.y*diameter);pointMin=pointMin.min(vertex.position.subtract(deltaVector));pointMax=pointMax.max(vertex.position.add(deltaVector));}
|
||||
var max_curve_length=32;for(i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if(edge.model.type==EdgeModels.curve)
|
||||
{var max_curve=edge.vertex2.position.subtract(edge.vertex1.position).length()/max_curve_length;for(j=0;j<max_curve;j++)
|
||||
{var point=edge.model.GetCurvePoint(edge.vertex1.position,edge.vertex2.position,j/max_curve);var deltaVector=new Point(max_curve_length,max_curve_length);pointMin=pointMin.min(point.subtract(deltaVector));pointMax=pointMax.max(point.add(deltaVector));}}}
|
||||
return new Rect(pointMin,pointMax);}
|
||||
Graph.prototype.hasPair=function(edge)
|
||||
{return this.FindPairFor(edge)!=null;}
|
||||
Graph.prototype.FindPairFor=function(edge)
|
||||
{var res=this.getNeighborEdges(edge);return res.length==1?res[0]:null;}
|
||||
Graph.prototype.getNeighborEdges=function(edge)
|
||||
{var res=[];for(var i=0;i<this.edges.length;i++)
|
||||
{var curEdge=this.edges[i];if(curEdge==edge)
|
||||
continue;if((curEdge.vertex1.id==edge.vertex1.id&&curEdge.vertex2.id==edge.vertex2.id)||(curEdge.vertex1.id==edge.vertex2.id&&curEdge.vertex2.id==edge.vertex1.id))
|
||||
{res.push(curEdge);}}
|
||||
return res;}
|
||||
Graph.prototype.checkMutiGraph=function()
|
||||
{var res=false;var start={};for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if(start.hasOwnProperty(edge.vertex1.id)&&start[edge.vertex1.id]==edge.vertex2.id)
|
||||
{res=true;break;}
|
||||
start[edge.vertex1.id]=edge.vertex2.id;if(!edge.isDirect)
|
||||
{if(start.hasOwnProperty(edge.vertex2.id)&&start[edge.vertex2.id]==edge.vertex1.id)
|
||||
{res=true;break;}
|
||||
start[edge.vertex2.id]=edge.vertex1.id;}}
|
||||
return res;}
|
||||
Graph.prototype.isMulti=function()
|
||||
{return this.isMultiGraph;}
|
||||
Graph.prototype.isNeedReposition=function()
|
||||
{var res=false;for(var i=0;i<this.vertices.length;i++)
|
||||
{res=res||this.vertices[i].IsUndefinedPosition();}
|
||||
return res;}
|
||||
Graph.prototype.FixEdgeCurve=function(edgeIndex)
|
||||
{var edgeObject=this.edges[edgeIndex];var hasPair=this.hasPair(edgeObject);var neighborEdges=this.getNeighborEdges(edgeObject);if(hasPair)
|
||||
{if(edgeObject.model.default)
|
||||
edgeObject.model.type=EdgeModels.curve;var pairEdge=this.FindPairFor(edgeObject);if(pairEdge.model.default)
|
||||
{pairEdge.model.type=EdgeModels.curve;if(pairEdge.vertex1==edgeObject.vertex1&&pairEdge.vertex2==edgeObject.vertex2)
|
||||
pairEdge.model.curveValue=-pairEdge.model.curveValue;}}
|
||||
else if(neighborEdges.length>=2)
|
||||
{var curve=this.GetAvailableCurveValue(neighborEdges,edgeObject);if(edgeObject.model.default)
|
||||
{edgeObject.model.type=EdgeModels.curve;edgeObject.model.curveValue=curve;}}}
|
||||
Graph.prototype.GetAvailableCurveValue=function(neighborEdges,originalEdge)
|
||||
{var values=[];for(var i=0;i<neighborEdges.length;i++)
|
||||
{var edge=neighborEdges[i];var sameDirection=(originalEdge.vertex1.id==edge.vertex1.id);if(edge.model.type==EdgeModels.curve)
|
||||
{values[(sameDirection?edge.model.curveValue:-edge.model.curveValue)]=true;}}
|
||||
var changeValue=DefaultHandler.prototype.curveValue;var defaultValue=0.0;var maxSearch=10;for(var i=1;i<maxSearch;i++)
|
||||
{value=i*changeValue;if(!values.hasOwnProperty(value))
|
||||
return value;value=-i*changeValue;if(!values.hasOwnProperty(value))
|
||||
return value;}
|
||||
return defaultValue;}
|
||||
Graph.prototype.reverseAllEdges=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{let v1=this.edges[i].vertex1;this.edges[i].vertex1=this.edges[i].vertex2;this.edges[i].vertex2=v1;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.makeAllEdgesDirected=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(!this.edges[i].isDirect)
|
||||
{this.edges[i].isDirect=true;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.makeAllEdgesUndirected=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{this.edges[i].isDirect=false;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
moduleLoader.endCacheLoading();
|
11
script/pages/create_graph_by_incidence_matrix/api/index.js
Normal file
11
script/pages/create_graph_by_incidence_matrix/api/index.js
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
// Global version needs to force reload scripts from server.
|
||||
globalVersion = 75;
|
||||
|
||||
{
|
||||
let modulDir = "pages/create_graph_by_matrix/";
|
||||
|
||||
doInclude ([
|
||||
include ("entities/graph/api/index.js")
|
||||
]);
|
||||
}
|
594
script/pages/create_graph_by_incidence_matrix/api/index.js.cache
Normal file
594
script/pages/create_graph_by_incidence_matrix/api/index.js.cache
Normal file
@ -0,0 +1,594 @@
|
||||
moduleLoader.beginCacheLoading(["/script/entities/graph/api/index.js?v=75","/script/shared/point.js?v=75","/script/entities/edge/api/index.js?v=75","/script/entities/edge/model/BaseEdge.js?v=75","/script/entities/edge/model/EdgeModel.js?v=75","/script/entities/vertex/api/index.js?v=75","/script/entities/vertex/model/BaseVertex.js?v=75","/script/entities/vertex/model/VertexModel.js?v=75","/script/entities/graph/model/Graph.js?v=75",]);globalVersion=75;{let modulDir="pages/create_graph_by_matrix/";doInclude([include("entities/graph/api/index.js")]);}
|
||||
{let modulDir="entities/graph/";doInclude([include("shared/point.js"),include("entities/edge/api/index.js"),include("entities/vertex/api/index.js"),include("model/Graph.js",modulDir)])}function Point(x,y){this.x=x||0;this.y=y||0;};Point.prototype.x=null;Point.prototype.y=null;Point.prototype.add=function(v){return new Point(this.x+v.x,this.y+v.y);};Point.prototype.addValue=function(v){return new Point(this.x+v,this.y+v);};Point.prototype.clone=function(){return new Point(this.x,this.y);};Point.prototype.degreesTo=function(v){var dx=this.x-v.x;var dy=this.y-v.y;var angle=Math.atan2(dy,dx);return angle*(180/Math.PI);};Point.prototype.distance=function(v){return Math.sqrt(this.distanceSqr(v));};Point.prototype.distanceSqr=function(v){var x=this.x-v.x;var y=this.y-v.y;return x*x+y*y;};Point.prototype.equals=function(toCompare){return this.x==toCompare.x&&this.y==toCompare.y;};Point.prototype.interpolate=function(v,f){return new Point((this.x+v.x)*f,(this.y+v.y)*f);};Point.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};Point.prototype.normalize=function(thickness){var l=this.length();this.x=this.x/l*thickness;this.y=this.y/l*thickness;return new Point(this.x,this.y);};Point.prototype.normalizeCopy=function(thickness){var l=this.length();return new Point(this.x/l*thickness,this.y/l*thickness);};Point.prototype.orbit=function(origin,arcWidth,arcHeight,degrees){var radians=degrees*(Math.PI/180);this.x=origin.x+arcWidth*Math.cos(radians);this.y=origin.y+arcHeight*Math.sin(radians);};Point.prototype.rotate=function(center,degrees){var radians=degrees*(Math.PI/180);offset=this.subtract(center);this.x=offset.x*Math.cos(radians)-offset.y*Math.sin(radians);this.y=offset.x*Math.sin(radians)+offset.y*Math.cos(radians);this.x=this.x+center.x;this.y=this.y+center.y;return this;};Point.prototype.offset=function(dx,dy){this.x+=dx;this.y+=dy;};Point.prototype.subtract=function(v){return new Point(this.x-v.x,this.y-v.y);};Point.prototype.subtractValue=function(value){return new Point(this.x-value,this.y-value);};Point.prototype.multiply=function(value){return new Point(this.x*value,this.y*value);};Point.prototype.toString=function(){return"(x="+this.x+", y="+this.y+")";};Point.prototype.normal=function(){return new Point(-this.y,this.x);};Point.prototype.min=function(point)
|
||||
{return new Point(Math.min(this.x,point.x),Math.min(this.y,point.y));};Point.prototype.max=function(point)
|
||||
{return new Point(Math.max(this.x,point.x),Math.max(this.y,point.y));};Point.prototype.inverse=function()
|
||||
{return new Point(-this.x,-this.y);};Point.prototype.cross=function(point)
|
||||
{return this.x*point.y-this.y*point.x;};Point.interpolate=function(pt1,pt2,f){return new Point(pt1.x*(1.0-f)+pt2.x*f,pt1.y*(1.0-f)+pt2.y*f);};Point.polar=function(len,angle){return new Point(len*Math.cos(angle),len*Math.sin(angle));};Point.distance=function(pt1,pt2){var x=pt1.x-pt2.x;var y=pt1.y-pt2.y;return Math.sqrt(x*x+y*y);};Point.center=function(pt1,pt2){return new Point((pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0);};Point.toString=function(){return x+" "+y;}
|
||||
Point.projection=function(point,line1,line2)
|
||||
{var x=line2.y-line1.y;var y=line1.x-line2.x;var l=(line1.cross(line2)+line1.cross(point)+line2.cross(point))/(x*(line2.y-line1.y)+y*(line1.x-line2.x));var res=new Point(point.x+x*l,point.y+y*l);return res;}
|
||||
Point.hitTest=function(pt11,pt12,pt21,pt22)
|
||||
{var res=null;var n=0.0;var x1=pt11.x;var y1=pt11.y;var x2=pt12.x;var y2=pt12.y;var x3=pt21.x;var y3=pt21.y;var x4=pt22.x;var y4=pt22.y;if(y2-y1!=0.0)
|
||||
{var q=(x2-x1)/(y1-y2);var sn=(x3-x4)+(y3-y4)*q;if(sn==0.0)
|
||||
{return res;}
|
||||
var fn=(x3-x1)+(y3-y1)*q;n=fn/sn;}
|
||||
else
|
||||
{if((y3-y4)==0.0)
|
||||
{return res;}
|
||||
n=(y3-y1)/(y3-y4);}
|
||||
res=new Point(x3+(x4-x3)*n,y3+(y4-y3)*n);var epsilon=1E-5;if(!(res.x>=Math.min(x1,x2)-epsilon&&res.x>=Math.min(x3,x4)-epsilon&&res.x<=Math.max(x1,x2)+epsilon&&res.x<=Math.max(x3,x4)+epsilon&&res.y>=Math.min(y1,y2)-epsilon&&res.y>=Math.min(y3,y4)-epsilon&&res.y<=Math.max(y1,y2)+epsilon&&res.y<=Math.max(y3,y4)+epsilon))
|
||||
{res=null;}
|
||||
return res;}
|
||||
function Rect(minPoint,maxPoint){this.minPoint=minPoint;this.maxPoint=maxPoint;};Rect.prototype.center=function()
|
||||
{return Point.center(this.minPoint,this.maxPoint);};Rect.prototype.size=function()
|
||||
{return this.maxPoint.subtract(this.minPoint);};Rect.prototype.left=function()
|
||||
{return this.minPoint.x;};Rect.prototype.top=function()
|
||||
{return this.minPoint.y;};Rect.prototype.isIn=function(v)
|
||||
{return this.minPoint.x<=v.x&&this.minPoint.y<=v.y&&this.maxPoint.x>v.x&&this.maxPoint.y>v.y;};{let modulDir="entities/edge/";doInclude([include("model/BaseEdge.js",modulDir),include("model/EdgeModel.js",modulDir)])}
|
||||
function BaseEdge(vertex1,vertex2,isDirect,weight,upText)
|
||||
{this.vertex1=vertex1;this.vertex2=vertex2;this.arrayStyleStart="";this.arrayStyleFinish="";this.isDirect=isDirect;this.weight=0;this.text="";this.useWeight=false;this.id=0;this.model=new EdgeModel();if(upText===undefined)
|
||||
this.upText="";else
|
||||
this.upText=upText;if(weight!==undefined)
|
||||
this.SetWeight(weight);this.ownStyles={};}
|
||||
BaseEdge.prototype.copyFrom=function(other)
|
||||
{this.vertex1=other.vertex1;this.vertex2=other.vertex2;this.arrayStyleStart=other.arrayStyleStart;this.arrayStyleFinish=other.arrayStyleFinish;this.isDirect=other.isDirect;this.weight=other.weight;this.text=other.text;this.useWeight=other.useWeight;this.id=other.id;this.model=new EdgeModel();this.model.copyFrom(other.model);this.upText=other.upText;this.ownStyles=FullObjectCopy(other.ownStyles);}
|
||||
BaseEdge.prototype.SaveToXML=function()
|
||||
{return"<edge "+"source=\""+this.vertex1.id+"\" "+"target=\""+this.vertex2.id+"\" "+"isDirect=\""+this.isDirect+"\" "+"weight=\""+this.weight+"\" "+"useWeight=\""+this.useWeight+"\" "+"id=\""+this.id+"\" "+"text=\""+gEncodeToHTML(this.text)+"\" "+"upText=\""+gEncodeToHTML(this.upText)+"\" "+"arrayStyleStart=\""+this.arrayStyleStart+"\" "+"arrayStyleFinish=\""+this.arrayStyleFinish+"\" "+
|
||||
((Object.keys(this.ownStyles).length>0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+
|
||||
this.model.SaveToXML()+"></edge>";}
|
||||
BaseEdge.prototype.LoadFromXML=function(xml,graph)
|
||||
{var attr=xml.attr('vertex1');if(typeof attr==='undefined')
|
||||
{attr=xml.attr('source');}
|
||||
this.vertex1=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph1'));var attr=xml.attr('vertex2');if(typeof attr==='undefined')
|
||||
{attr=xml.attr('target');}
|
||||
this.vertex2=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph2'));this.isDirect=xml.attr('isDirect')=="true";this.weight=parseFloat(xml.attr('weight'));if(isNaN(this.weight))
|
||||
{this.weight=1;}
|
||||
this.hasPair=xml.attr('hasPair')=="true";this.useWeight=xml.attr('useWeight')=="true";this.id=xml.attr('id');this.text=xml.attr("text")==null?"":gDecodeFromHTML(xml.attr("text"));this.arrayStyleStart=xml.attr("arrayStyleStart")==null?"":xml.attr("arrayStyleStart");this.arrayStyleFinish=xml.attr("arrayStyleFinish")==null?"":xml.attr("arrayStyleFinish");this.upText=xml.attr('upText');if(typeof this.upText==='undefined')
|
||||
{this.upText="";}
|
||||
else
|
||||
{this.upText=gDecodeFromHTML(this.upText);}
|
||||
var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined')
|
||||
{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave)
|
||||
{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField])
|
||||
{if(this.ownStyles[index].ShouldLoad(field))
|
||||
this.ownStyles[index][field]=parsedSave[indexField][field];}}}
|
||||
this.model.LoadFromXML(xml);}
|
||||
BaseEdge.prototype.GetPixelLength=function()
|
||||
{if(this.vertex1==this.vertex2)
|
||||
{return this.model.GetLoopSize()*2*Math.PI;}
|
||||
else
|
||||
{return Point.distance(this.vertex1.position,this.vertex2.position);}}
|
||||
BaseEdge.prototype.GetWeight=function()
|
||||
{return this.useWeight?this.weight:1;}
|
||||
BaseEdge.prototype.GetText=function()
|
||||
{return this.text.length>0?this.text:(this.useWeight?this.weight.toString():"");}
|
||||
BaseEdge.prototype.GetUpText=function()
|
||||
{return this.upText;}
|
||||
BaseEdge.prototype.GetStartEdgeStyle=function()
|
||||
{return this.arrayStyleStart;}
|
||||
BaseEdge.prototype.GetFinishEdgeStyle=function()
|
||||
{return(this.arrayStyleFinish!=""?this.arrayStyleFinish:(this.isDirect?"arrow":""));}
|
||||
BaseEdge.prototype.HitTest=function(pos)
|
||||
{var positions=this.GetEdgePositionsShift();return this.model.HitTest(positions[0],positions[1],pos);}
|
||||
BaseEdge.prototype.GetEdgePositionsShift=function()
|
||||
{return this.GetEdgePositions();}
|
||||
BaseEdge.prototype.GetEdgePositions=function()
|
||||
{var res=[];if(this.vertex1==this.vertex2)
|
||||
{res.push(this.vertex1.position);res.push(this.vertex2.position);return res;}
|
||||
var position1=this.vertex1.position;var position2=this.vertex2.position;var diameter1=this.vertex1.model.diameter+parseInt(this.vertex1.currentStyle.GetStyle({},this.vertex1).lineWidth);var diameter2=this.vertex2.model.diameter+parseInt(this.vertex2.currentStyle.GetStyle({},this.vertex2).lineWidth);var direction=position1.subtract(position2);var direction1=direction;var direction2=direction;var d1=diameter1;var d2=diameter2;if(this.model.type==EdgeModels.curve)
|
||||
{var dist=position1.distance(position2);var point1=this.model.GetCurvePoint(position1,position2,10.0/dist);direction1=position1.subtract(point1);var point2=this.model.GetCurvePoint(position1,position2,1.0-10.0/dist);direction2=position2.subtract(point2);d2=diameter2;}
|
||||
else
|
||||
{direction2=direction2.multiply(-1);}
|
||||
direction1.normalize(1.0);direction2.normalize(1.0);var vertices=[];vertices.push({vertex:this.vertex1,direction:direction1,position:position1,diameter:d1});vertices.push({vertex:this.vertex2,direction:direction2,position:position2,diameter:d2});vertices.forEach(function(data)
|
||||
{var shape=data.vertex.currentStyle.GetStyle({},data.vertex).shape;if(shape==VertexCircleShape)
|
||||
{var direction=data.direction.multiply(0.5);res.push(data.position.subtract(direction.multiply(data.diameter)));}
|
||||
else
|
||||
{var lineFinish1=data.direction.multiply(-1).multiply(1000.0);var pointsVertex1=GetPointsForShape(shape,data.diameter,data.vertex.mainText);pointsVertex1.push(pointsVertex1[0]);for(var i=0;i<pointsVertex1.length-1;i++)
|
||||
{var hitText=Point.hitTest(new Point(0,0),lineFinish1,pointsVertex1[i],pointsVertex1[i+1]);if(hitText!=null)
|
||||
{res.push(data.position.add(hitText));break;}}}});return res;}
|
||||
BaseEdge.prototype.SetWeight=function(weight)
|
||||
{var useWeight=false;if(!isNaN(parseInt(weight,10)))
|
||||
{useWeight=true;}
|
||||
weight=(!isNaN(parseInt(weight,10))&&weight>=0)?weight:1;this.weight=Number(weight);this.useWeight=useWeight;}
|
||||
BaseEdge.prototype.SetUpText=function(text)
|
||||
{this.upText=text;}
|
||||
BaseEdge.prototype.resetOwnStyle=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{delete this.ownStyles[index];}}
|
||||
BaseEdge.prototype.setOwnStyle=function(index,style)
|
||||
{this.ownStyles[index]=style;}
|
||||
BaseEdge.prototype.getStyleFor=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{return this.ownStyles[index];}
|
||||
else
|
||||
{var style=null;if(index==0)
|
||||
style=globalApplication.GetStyle("edge","common");else
|
||||
style=globalApplication.GetStyle("edge","selected",undefined,index-1);return style;}}
|
||||
BaseEdge.prototype.hasOwnStyleFor=function(index)
|
||||
{return this.ownStyles.hasOwnProperty(index);}
|
||||
var EdgeModels={"line":0,"curve":1};const defaultEdgeWidth=4;function EdgeModel()
|
||||
{this.width=globalApplication.GetDefaultEdgeWidth();this.type=EdgeModels.line;this.curveValue=EdgeModel.prototype.defaultCurve;this.default=true;this.sizeOfLoop=24;this.loopShiftAngel=Math.PI/6;}
|
||||
EdgeModel.prototype.defaultCurve=0.1;EdgeModel.prototype.copyFrom=function(other)
|
||||
{this.width=other.width;this.type=other.type;this.curveValue=other.curveValue;this.default=other.default;}
|
||||
EdgeModel.prototype.SaveToXML=function()
|
||||
{return"model_width=\""+this.width+"\" "+"model_type=\""+this.type+"\" "+"model_curveValue=\""+this.curveValue+"\" "+"model_default=\""+this.default+"\" ";}
|
||||
EdgeModel.prototype.LoadFromXML=function(xml,graph)
|
||||
{this.width=xml.attr('model_width')==null?this.width:parseFloat(xml.attr("model_width"));this.type=xml.attr('model_type')==null?this.type:xml.attr("model_type");this.curveValue=xml.attr('model_curveValue')==null?this.curveValue:parseFloat(xml.attr("model_curveValue"));this.default=xml.attr('model_default')==null?this.default:parseFloat(xml.attr("model_default"));}
|
||||
EdgeModel.prototype.GetCurvePoint=function(position1,position2,t)
|
||||
{var points=this.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];var B0_t=Math.pow(1-t,3);var B1_t=3*t*Math.pow(1-t,2);var B2_t=3*t*t*(1-t)
|
||||
var B3_t=t*t*t;var ax=position1.x;var ay=position1.y;var dx=position2.x;var dy=position2.y;var bx=firstBezierPoint.x;var by=firstBezierPoint.y;var cx=secondBezierPoint.x;var cy=secondBezierPoint.y;var px_t=(B0_t*ax)+(B1_t*bx)+(B2_t*cx)+(B3_t*dx);var py_t=(B0_t*ay)+(B1_t*by)+(B2_t*cy)+(B3_t*dy);return new Point(px_t,py_t);}
|
||||
EdgeModel.prototype.GetBezierPoints=function(position1,position2)
|
||||
{var direction=position2.subtract(position1);var delta=direction.length();direction.normalize(1.0);var normal=direction.normal();var deltaOffsetPixels=delta*this.curveValue;var yOffset=normal.multiply(deltaOffsetPixels);var firstBezierPointShift=(direction.multiply(delta*0.2)).add(yOffset);var secondBezierPointShift=(direction.multiply(-delta*0.2)).add(yOffset);var firstBezierPoint=position1.add(firstBezierPointShift);var secondBezierPoint=position2.add(secondBezierPointShift);return[firstBezierPoint,secondBezierPoint];}
|
||||
EdgeModel.prototype.HitTest=function(position1,position2,mousePos)
|
||||
{if(this.type==EdgeModels.line)
|
||||
return this.HitTestLine(position1,position2,mousePos);else if(this.type==EdgeModels.curve)
|
||||
return this.HitTestCurve(position1,position2,mousePos);return false;}
|
||||
EdgeModel.prototype.HitTestLine=function(position1,position2,mousePos,factor)
|
||||
{if(factor===undefined)
|
||||
{factor=1.0;}
|
||||
var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2))
|
||||
{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5*factor;}
|
||||
var r1=pos0.distance(pos1);var r2=pos0.distance(pos2);var r12=pos1.distance(pos2);if(r1>=(new Point(r2,r12)).length()||r2>=(new Point(r1,r12)).length())
|
||||
{}
|
||||
else
|
||||
{var distance=((pos1.y-pos2.y)*pos0.x+(pos2.x-pos1.x)*pos0.y+(pos1.x*pos2.y-pos2.x*pos1.y))/r12;if(Math.abs(distance)<=this.width*1.5*factor)
|
||||
{return true;}}
|
||||
return false;}
|
||||
EdgeModel.prototype.HitTestCurve=function(position1,position2,mousePos)
|
||||
{var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2))
|
||||
{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5;}
|
||||
var interval_count=position1.distance(position2)/100*30;var start=position1;for(var i=0;i<interval_count;i++)
|
||||
{var finish=this.GetCurvePoint(position1,position2,i/interval_count);if(this.HitTestLine(start,finish,mousePos,2.0))
|
||||
return true;start=finish;}
|
||||
return false;}
|
||||
EdgeModel.prototype.ChangeCurveValue=function(delta)
|
||||
{if(this.type==EdgeModels.line)
|
||||
{this.type=EdgeModels.curve;this.curveValue=0.0;}
|
||||
this.curveValue=this.curveValue+delta;if(Math.abs(this.curveValue)<=0.01)
|
||||
this.type=EdgeModels.line;this.default=false;}
|
||||
EdgeModel.prototype.SetCurveValue=function(value)
|
||||
{if(this.type==EdgeModels.line)
|
||||
{this.type=EdgeModels.curve;this.curveValue=0.0;}
|
||||
this.curveValue=value;if(Math.abs(this.curveValue)<=0.01)
|
||||
this.type=EdgeModels.line;this.default=false;}
|
||||
EdgeModel.prototype.GetLoopSize=function()
|
||||
{if(Math.abs(this.curveValue)<=0.01)
|
||||
{return this.sizeOfLoop;}
|
||||
else
|
||||
{let normalCurve=this.curveValue;if(this.type==EdgeModels.line){normalCurve=this.defaultCurve;}
|
||||
else if(normalCurve>=0.0){normalCurve+=this.defaultCurve}
|
||||
return this.sizeOfLoop*Math.abs(normalCurve)*(1/this.defaultCurve);}}
|
||||
EdgeModel.prototype.GetLoopShiftAngel=function()
|
||||
{if(this.type==EdgeModels.line||this.curveValue>=0.0)
|
||||
{return this.loopShiftAngel;}
|
||||
else
|
||||
{return this.loopShiftAngel+Math.PI;}}
|
||||
{let modulDir="entities/vertex/";doInclude([include("model/BaseVertex.js",modulDir),include("model/VertexModel.js",modulDir)])}
|
||||
function BaseVertex(x,y,vertexEnumType)
|
||||
{this.position=new Point(x,y);this.id=0;this.mainText="";this.upText="";this.vertexEnumType=vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=false;this.ownStyles={};};BaseVertex.prototype.position=new Point(0,0);BaseVertex.prototype.copyFrom=function(other)
|
||||
{this.position=new Point(other.position.x,other.position.y);this.id=other.id;this.mainText=other.mainText;this.upText=other.upText;this.vertexEnumType=other.vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=other.hasUndefinedPosition;this.ownStyles=FullObjectCopy(other.ownStyles);}
|
||||
BaseVertex.prototype.SaveToXML=function()
|
||||
{return"<node "+"positionX=\""+this.position.x+"\" "+"positionY=\""+this.position.y+"\" "+"id=\""+this.id+"\" "+"mainText=\""+gEncodeToHTML(this.mainText)+"\" "+"upText=\""+gEncodeToHTML(this.upText)+"\" "+
|
||||
((Object.keys(this.ownStyles).length>0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+"size=\""+this.model.diameter+"\" "+"></node>";}
|
||||
BaseVertex.prototype.LoadFromXML=function(xml)
|
||||
{var xmlX=xml.attr('positionX');var xmlY=xml.attr('positionY');this.hasUndefinedPosition=(typeof xmlX==='undefined')||(typeof xmlY==='undefined');this.position=new Point(parseFloat(xmlX),parseFloat(xmlY));this.id=xml.attr('id');this.mainText=xml.attr('mainText');this.upText=xml.attr('upText');if(typeof this.mainText==='undefined')
|
||||
this.mainText=this.id;else
|
||||
this.mainText=gDecodeFromHTML(this.mainText);if(typeof this.upText==='undefined')
|
||||
this.upText="";else
|
||||
this.upText=gDecodeFromHTML(this.upText);var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined')
|
||||
{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave)
|
||||
{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField])
|
||||
{if(this.ownStyles[index].ShouldLoad(field))
|
||||
this.ownStyles[index][field]=parsedSave[indexField][field];}}}
|
||||
var size=xml.attr('size');if(typeof size!=='undefined')
|
||||
this.model.diameter=parseInt(size);}
|
||||
BaseVertex.prototype.SetId=function(id)
|
||||
{this.id=id;if(this.vertexEnumType!=null)
|
||||
this.mainText=this.vertexEnumType.GetVertexText(id);}
|
||||
BaseVertex.prototype.diameterFactor=function()
|
||||
{return new Point(1.0+(this.mainText.length?this.mainText.length/8.0:0),1.5);}
|
||||
BaseVertex.prototype.IsUndefinedPosition=function()
|
||||
{return this.hasUndefinedPosition;}
|
||||
BaseVertex.prototype.HitTest=function(pos)
|
||||
{var shape=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).shape:VertexCircleShape;var width=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).lineWidth:0;if(shape==VertexCircleShape)
|
||||
{return this.position.distance(pos)<this.model.diameter/2.0+width;}
|
||||
else
|
||||
{var relativePos=(new Point(pos.x,pos.y)).subtract(this.position);var lineFinish1=relativePos.add(new Point(1000,0));var lineFinish2=relativePos.add(new Point(-1000,0));var pointsVertex1=GetPointsForShape(shape,this.model.diameter+width,this.mainText);pointsVertex1.push(pointsVertex1[0]);var hitNumber1=0;var hitNumber2=0;for(var i=0;i<pointsVertex1.length-1;i++)
|
||||
{var hitTest=Point.hitTest(relativePos,lineFinish1,pointsVertex1[i],pointsVertex1[i+1]);if(hitTest!=null)
|
||||
{hitNumber1++;}
|
||||
hitTest=Point.hitTest(relativePos,lineFinish2,pointsVertex1[i],pointsVertex1[i+1]);if(hitTest!=null)
|
||||
{hitNumber2++;}}
|
||||
return hitNumber1==1&&hitNumber2==1;}
|
||||
return false;}
|
||||
BaseVertex.prototype.resetOwnStyle=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{delete this.ownStyles[index];}}
|
||||
BaseVertex.prototype.setOwnStyle=function(index,style)
|
||||
{this.ownStyles[index]=FullObjectCopy(style);}
|
||||
BaseVertex.prototype.getStyleFor=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{return this.ownStyles[index];}
|
||||
else
|
||||
{var style=null;if(index==0)
|
||||
style=globalApplication.GetStyle("vertex","common");else
|
||||
style=globalApplication.GetStyle("vertex","selected",undefined,index-1);return style;}}
|
||||
BaseVertex.prototype.hasOwnStyleFor=function(index)
|
||||
{return this.ownStyles.hasOwnProperty(index);}
|
||||
const defaultVertexDiameter=30;function VertexModel()
|
||||
{this.diameter=globalApplication.GetDefaultVertexSize();}
|
||||
function Graph()
|
||||
{this.vertices=[];this.edges=[];this.uidGraph=0;this.uidEdge=10000;this.hasDirect=false;this.isMultiGraph=false;};Graph.prototype.infinity=1E8;Graph.prototype.maxVertices=1000;Graph.prototype.edgesOffset=10000;Graph.prototype.AddNewVertex=function(vertex)
|
||||
{if(this.vertices.length<=this.maxVertices)
|
||||
{vertex.SetId(this.uidGraph);this.uidGraph=this.uidGraph+1;this.vertices.push(vertex);}
|
||||
return this.vertices.length-1;}
|
||||
Graph.prototype.ClearGraph=function(){this.vertices=[];this.edges=[];this.uidGraph=0;this.uidEdge=10000;this.hasDirect=false;this.isMultiGraph=false;}
|
||||
Graph.prototype.AddNewEdgeSafe=function(graph1,graph2,isDirect,weight,replaceIfExists=true)
|
||||
{return this.AddNewEdge(new BaseEdge(graph1,graph2,isDirect,weight),replaceIfExists);}
|
||||
Graph.prototype.AddNewEdge=function(edge,replaceIfExists)
|
||||
{edge.id=this.uidEdge;this.uidEdge=this.uidEdge+1;var edge1=this.FindEdgeAny(edge.vertex1.id,edge.vertex2.id);var edgeRevert=this.FindEdgeAny(edge.vertex2.id,edge.vertex1.id);if(!edge.isDirect)
|
||||
{if(edge1!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edge1);if(edgeRevert!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edgeRevert);this.edges.push(edge);}
|
||||
else
|
||||
{if(edge1!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edge1);if(edgeRevert!=null&&!edgeRevert.isDirect&&replaceIfExists)
|
||||
this.DeleteEdge(edgeRevert);this.edges.push(edge);}
|
||||
this.isMultiGraph=this.checkMutiGraph();return this.edges.length-1;}
|
||||
Graph.prototype.DeleteEdge=function(edgeObject)
|
||||
{var index=this.edges.indexOf(edgeObject);if(index>-1)
|
||||
{this.edges.splice(index,1);}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.DeleteVertex=function(vertexObject)
|
||||
{var index=this.vertices.indexOf(vertexObject);if(index>-1)
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].vertex1==vertexObject||this.edges[i].vertex2==vertexObject)
|
||||
{this.DeleteEdge(this.edges[i]);i--;}}
|
||||
this.vertices.splice(index,1);}}
|
||||
Graph.prototype.HasConnectedNodes=function(vertexObject)
|
||||
{var res=false;var index=this.vertices.indexOf(vertexObject);if(index>-1)
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].vertex1==vertexObject||this.edges[i].vertex2==vertexObject)
|
||||
{res=true;break;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindVertex=function(id)
|
||||
{var res=null;for(var i=0;i<this.vertices.length;i++)
|
||||
{if(this.vertices[i].id==id)
|
||||
{res=this.vertices[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindVertexByTitle=function(title)
|
||||
{var res=null;for(var i=0;i<this.vertices.length;i++)
|
||||
{if(this.vertices[i].mainText==title)
|
||||
{res=this.vertices[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdge=function(id1,id2)
|
||||
{return this.FindEdgeAny(id1,id2);}
|
||||
Graph.prototype.FindEdgeById=function(edgeId)
|
||||
{var res=null;for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].id==edgeId)
|
||||
{res=this.edges[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeAny=function(id1,id2)
|
||||
{var res=null;for(var i=0;i<this.edges.length;i++)
|
||||
{if((this.edges[i].vertex1.id==id1&&this.edges[i].vertex2.id==id2)||(!this.edges[i].isDirect&&this.edges[i].vertex1.id==id2&&this.edges[i].vertex2.id==id1))
|
||||
{res=this.edges[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMin=function(id1,id2)
|
||||
{var res=null;var minWeight=this.infinity;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight<minWeight)
|
||||
{res=edge;minWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMax=function(id1,id2)
|
||||
{var res=null;var maxWeight=0;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight>maxWeight)
|
||||
{res=edge;maxWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMinIgnoreDirection=function(id1,id2)
|
||||
{var res=null;var minWeight=this.infinity;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight<minWeight)
|
||||
{res=edge;minWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindAllEdges=function(id1,id2)
|
||||
{var res=[];for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{res.push(edge);}}
|
||||
return res;}
|
||||
Graph.prototype.GetAdjacencyMatrixStr=function()
|
||||
{var matrix="";for(var i=0;i<this.vertices.length;i++)
|
||||
{for(var j=0;j<this.vertices.length;j++)
|
||||
{var edge=this.FindEdgeMin(this.vertices[i].id,this.vertices[j].id);if(edge!=null)
|
||||
{matrix+=edge.weight;}
|
||||
else
|
||||
{matrix+="0";}
|
||||
if(j!=this.vertices.length)
|
||||
{matrix+=", ";}}
|
||||
matrix=matrix+"\n";}
|
||||
return matrix;}
|
||||
Graph.prototype.GetAdjacencyMatrix=function()
|
||||
{var matrix=[];for(var i=0;i<this.vertices.length;i++)
|
||||
{matrix.push([]);var v1=this.vertices[i];for(var j=0;j<this.vertices.length;j++)
|
||||
{var v2=this.vertices[j];var edge=this.FindEdgeMin(v1.id,v2.id);if(edge!=null)
|
||||
{matrix[i][j]=edge.GetWeight();}
|
||||
else
|
||||
{matrix[i][j]=this.infinity;}}}
|
||||
return matrix;}
|
||||
Graph.prototype.TestAdjacencyMatrix=function(matrix,rowsObj,colsObj,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j<rowsObj.rows.length;++j)
|
||||
{if(rowsObj.rows[j]==="")
|
||||
{rowsObj.rows.splice(j--,1);}}
|
||||
colsObj.cols=[];for(var i=0;i<rowsObj.rows.length;i++)
|
||||
{colsObj.cols[i]=this.SplitMatrixString(rowsObj.rows[i],separator);for(j=0;j<colsObj.cols[i].length;++j)
|
||||
{if(colsObj.cols[i][j]==="")
|
||||
{colsObj.cols[i].splice(j--,1);}}
|
||||
if(colsObj.cols[i].length!=rowsObj.rows.length)
|
||||
{bGoodFormat=false;break;}}
|
||||
return bGoodFormat;}
|
||||
Graph.prototype.TestPair=function(pair)
|
||||
{let lines=pair.split("\n");let regExp=[/^.+-.+$/g,/^.+\>.+$/g,/^.+<.+$/g,/^.+-\(\d+\.?\d+\)-.+$/g,/^.+-\(\d+\.?\d+\)\>.+$/g,/^.+<\(\d+\.?\d+\)\-.+$/g];let res=true;for(let i=0;i<lines.length;++i)
|
||||
{let resLine=false;let line=lines[i];if(line==""){continue;}
|
||||
for(let j=0;j<regExp.length;++j){if(line.match(regExp[j])){resLine=true;}}
|
||||
res=resLine&&res;}
|
||||
return res;}
|
||||
Graph.prototype.IsVerticesHaveSamePosition=function(position,vertexCount)
|
||||
{var res=false;for(var j=0;j<Math.min(this.vertices.length,vertexCount);j++)
|
||||
{if(position.distance(this.vertices[j].position)<this.vertices[j].model.diameter*2)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.GetRandomPosition=function(viewportSize){return new Point(Math.random()*viewportSize.x,Math.random()*viewportSize.y);}
|
||||
Graph.prototype.GetRandomPositionOfVertex=function(matrix,vertexIndex,viewportSize)
|
||||
{var point=new Point(0,0);var relatedVertex=[];for(var j=0;j<matrix.length;j++)
|
||||
{if(j<this.vertices.length&&(cols[vertexIndex][j]>0||cols[j][vertexIndex]>0)&&j!=vertexIndex)
|
||||
{relatedVertex.push(this.vertices[j]);}}
|
||||
var diameter=(new VertexModel()).diameter;if(relatedVertex.length>1)
|
||||
{for(var j=0;j<relatedVertex.length;j++)
|
||||
{point=point.add(relatedVertex[j].position);}
|
||||
point=point.multiply(1/relatedVertex.length);point.offset(Math.random()*diameter+(Math.random()?-1:1)*2*diameter,Math.random()*diameter+(Math.random()?-1:1)*2*diameter);}
|
||||
else
|
||||
{point=new Point(Math.random()*viewportSize.x,Math.random()*viewportSize.y);}
|
||||
if(this.IsVerticesHaveSamePosition(point,matrix.length))
|
||||
{point.offset(Math.random()*diameter+ +(Math.random()?-1:1)*4*diameter,Math.random()*diameter+ +(Math.random()?-1:1)*4*diameter);}
|
||||
point.x=Math.min(Math.max(point.x,diameter),viewportSize.x);point.y=Math.min(Math.max(point.y,diameter),viewportSize.y);return point;}
|
||||
Graph.prototype.VerticesReposition=function(viewportSize,newVertices)
|
||||
{var maxGravityDistanceSqr=Math.max(viewportSize.x,viewportSize.y)/5.0;maxGravityDistanceSqr=maxGravityDistanceSqr*maxGravityDistanceSqr;var velocityDamping=0.85;var diameter=(new VertexModel()).diameter;var maxDistance=diameter*3;var gravityDistanceSqr=10*(maxDistance*maxDistance);var edgeGravityKof=10/(maxDistance);var kCenterForce=10/(maxDistance*10);var centerPoint=viewportSize.multiply(0.5);var velocityMax=maxDistance*10;var edgesMatrix={};for(var i=0;i<this.edges.length;i++)
|
||||
{edgesMatrix[this.edges[i].vertex1.id+this.edges[i].vertex2.id*1000]=1;edgesMatrix[this.edges[i].vertex2.id+this.edges[i].vertex1.id*1000]=1;}
|
||||
var startAngel=Math.random()*180.0;for(i=0;i<newVertices.length;i++)
|
||||
{newVertices[i].position.orbit(new Point(viewportSize.x/2,viewportSize.y/2),(viewportSize.x-diameter*2)/2,(viewportSize.y-diameter*2)/2,360*i/newVertices.length+startAngel);}
|
||||
var k=0;var bChanged=true;while(k<1000&&bChanged)
|
||||
{var vertexData=[];for(i=0;i<newVertices.length;i++)
|
||||
{var currentVertex={};currentVertex.object=newVertices[i];currentVertex.net_force=new Point(0,0);currentVertex.velocity=new Point(0,0);vertexData.push(currentVertex);for(j=0;j<this.vertices.length;j++)
|
||||
{otherVertex=this.vertices[j];if(otherVertex==currentVertex.object)continue;var rsq=currentVertex.object.position.distanceSqr(otherVertex.position);{var force=(currentVertex.object.position.subtract(otherVertex.position)).normalize(gravityDistanceSqr/rsq);currentVertex.net_force=currentVertex.net_force.add(force);}}
|
||||
for(j=0;j<this.vertices.length;j++)
|
||||
{otherVertex=this.vertices[j];if(edgesMatrix.hasOwnProperty(currentVertex.object.id+1000*otherVertex.id))
|
||||
{var distance=currentVertex.object.position.distance(otherVertex.position);if(distance>maxDistance)
|
||||
{var force=(otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof*(distance-maxDistance));currentVertex.net_force=currentVertex.net_force.add(force);}}}
|
||||
var distanceToCenter=centerPoint.distance(currentVertex.object.position);var force=centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter*kCenterForce);currentVertex.net_force=currentVertex.net_force.add(force);currentVertex.velocity=currentVertex.velocity.add(currentVertex.net_force);}
|
||||
bChanged=false;for(i=0;i<vertexData.length;i++)
|
||||
{var v=vertexData[i];var velocity=v.velocity;if(velocity.length()>velocityMax)
|
||||
{velocity=velocity.normalize(velocityMax);}
|
||||
v.object.position=v.object.position.add(velocity);if(velocity.length()>=1)
|
||||
{bChanged=true;}}
|
||||
k++;}
|
||||
var bbox=this.getGraphBBox();if(bbox.size().length()>viewportSize.length()*1000)
|
||||
{for(i=0;i<newVertices.length;i++)
|
||||
{newVertices[i].position.orbit(new Point(viewportSize.x/2,viewportSize.y/2),(viewportSize.x-diameter*2)/2,(viewportSize.y-diameter*2)/2,360*i/newVertices.length+startAngel);}}
|
||||
else
|
||||
{var count=10;var angle=360.0/count;var viewportAspect=viewportSize.x/viewportSize.y;var bestIndex=0;var graphSize=bbox.size();var bestAspect=graphSize.x/graphSize.y;var center=bbox.center();for(var i=1;i<count;i++)
|
||||
{for(j=0;j<newVertices.length;j++)
|
||||
{newVertices[j].position.rotate(center,angle);}
|
||||
var newBBox=this.getGraphBBox();var newAspect=newBBox.size().x/newBBox.size().y;if(Math.abs(newAspect-viewportAspect)<Math.abs(bestAspect-viewportAspect))
|
||||
{bestAspect=newAspect;bestIndex=i;}}
|
||||
for(j=0;j<newVertices.length;j++)
|
||||
{newVertices[j].position.rotate(center,-angle*(count-bestIndex-1));}}}
|
||||
Graph.prototype.SetAdjacencyMatrix=function(matrix,viewportSize,currentEnumVerticesType,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var rowsObj={};var colsObj={};if(this.TestAdjacencyMatrix(matrix,rowsObj,colsObj,separator))
|
||||
{rows=rowsObj.rows;cols=colsObj.cols;var clonedEdge=this.edges.slice(0);for(var i=0;i<clonedEdge.length;i++)
|
||||
{this.DeleteEdge(clonedEdge[i]);}
|
||||
var newVertices=[];var bWeightGraph=false;for(var i=0;i<rows.length;i++)
|
||||
{for(var j=0;j<rows.length;j++)
|
||||
{if(j>=this.vertices.length)
|
||||
{var newPos=this.GetRandomPositionOfVertex(matrix,j,viewportSize);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);}
|
||||
if(cols[i][j]>0)
|
||||
{var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[i],this.vertices[j],cols[i][j]!=cols[j][i],cols[i][j],true);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0)
|
||||
{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
for(var i=rows.length;i<Math.max(this.vertices.length,rows.length);i++)
|
||||
{this.DeleteVertex(this.vertices[i]);i--;}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.SetPair=function(pairs,viewportSize,currentEnumVerticesType)
|
||||
{if(this.TestPair(pairs))
|
||||
{this.ClearGraph();let lines=pairs.split("\n");let regExp=[/^(.+)-(.+)$/g,/^(.+)\>(.+)$/g,/^(.+)<(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)-(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)\>(.+)$/g,/^(.+)<\((\d+|\d+\.?\d+)\)\-(.+)$/g,];let bWeightGraph=false;var newVertices=[];for(var i=0;i<lines.length;i++)
|
||||
{let line=lines[i];if(line==""){continue;}
|
||||
for(let j=regExp.length-1;j>=0;--j){if(!line.match(regExp[j])){continue;}
|
||||
let groupes=Array.from(line.matchAll(regExp[j]));let groupe=groupes[0];let vetext1Title=groupe[1];let vertex1=this.FindVertexByTitle(vetext1Title);if(vertex1==null){let newPosition=this.GetRandomPosition(viewportSize);vertex1=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex1.mainText=vetext1Title;newVertices.push(vertex1);}
|
||||
let vetext2Title=groupe[j<=2?2:3];let vertex2=this.FindVertexByTitle(vetext2Title);if(vertex2==null){let newPosition=this.GetRandomPosition(viewportSize);vertex2=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex2.mainText=vetext2Title;newVertices.push(vertex2);}
|
||||
let isDirect=j==1||j==2||j==4||j==5;let weight=1;if(j>2){weight=groupe[2];bWeightGraph=true;}
|
||||
let isRevertEdge=j==2||j==5;let nEdgeIndex=this.AddNewEdgeSafe(isRevertEdge?vertex2:vertex1,isRevertEdge?vertex1:vertex2,isDirect,weight,false);this.FixEdgeCurve(nEdgeIndex);break;}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j<rowsObj.rows.length;++j)
|
||||
{if(rowsObj.rows[j]==="")
|
||||
{rowsObj.rows.splice(j--,1);}}
|
||||
colsObj.cols=[];var columnCount=0;for(var i=0;i<rowsObj.rows.length;i++)
|
||||
{colsObj.cols[i]=this.SplitMatrixString(rowsObj.rows[i],separator);for(j=0;j<colsObj.cols[i].length;++j)
|
||||
{if(colsObj.cols[i][j]==="")
|
||||
{colsObj.cols[i].splice(j--,1);}}
|
||||
if(i==0)
|
||||
{columnCount=colsObj.cols[i].length;}
|
||||
if(colsObj.cols[i].length!=columnCount)
|
||||
{bGoodFormat=false;break;}}
|
||||
if(bGoodFormat)
|
||||
{for(var i=0;i<colsObj.cols[0].length;i++)
|
||||
{var values=[];for(j=0;j<colsObj.cols.length;++j)
|
||||
{if(colsObj.cols[j][i]!=0)
|
||||
{values.push(colsObj.cols[j][i]);}}
|
||||
if(!(values.length<=1||(values.length==2&&(values[0]==values[1]||values[0]==-values[1]))))
|
||||
{bGoodFormat=false;break;}}}
|
||||
return bGoodFormat;}
|
||||
Graph.prototype.SetIncidenceMatrix=function(matrix,viewportSize,currentEnumVerticesType)
|
||||
{var rowsObj={};var colsObj={};if(this.TestIncidenceMatrix(matrix,rowsObj,colsObj))
|
||||
{rows=rowsObj.rows;cols=colsObj.cols;var clonedEdge=this.edges.slice(0);for(var i=0;i<clonedEdge.length;i++)
|
||||
{this.DeleteEdge(clonedEdge[i]);}
|
||||
var newVertices=[];var bWeightGraph=false;for(var i=0;i<cols[0].length;i++)
|
||||
{var edgeValue=[];var edgeIndex=[];for(var j=0;j<cols.length;j++)
|
||||
{if(j>=this.vertices.length)
|
||||
{var newPos=new Point(0,0);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);}
|
||||
if(cols[j][i]!=0)
|
||||
{edgeValue.push(cols[j][i]);edgeIndex.push(j);}}
|
||||
if(edgeIndex.length==1)
|
||||
{edgeValue.push(edgeValue[0]);edgeIndex.push(edgeIndex[0]);}
|
||||
if(edgeIndex.length==2)
|
||||
{if(edgeValue[0]!=edgeValue[1])
|
||||
{if(edgeValue[1]>0)
|
||||
{edgeValue=edgeValue.swap(0,1);edgeIndex=edgeIndex.swap(0,1);}}
|
||||
var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[edgeIndex[0]],this.vertices[edgeIndex[1]],edgeValue[0]!=edgeValue[1],Math.abs(edgeValue[1]),false);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0)
|
||||
{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
for(var i=cols.length;i<Math.max(this.vertices.length,cols.length);i++)
|
||||
{this.DeleteVertex(this.vertices[i]);i--;}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.GetIncidenceMatrix=function()
|
||||
{var matrix="";for(var i=0;i<this.vertices.length;i++)
|
||||
{for(var j=0;j<this.edges.length;j++)
|
||||
{if(this.edges[j].vertex1==this.vertices[i])
|
||||
{matrix+=this.edges[j].weight;}
|
||||
else if(this.edges[j].vertex2==this.vertices[i]&&!this.edges[j].isDirect)
|
||||
{matrix+=this.edges[j].weight;}
|
||||
else if(this.edges[j].vertex2==this.vertices[i]&&this.edges[j].isDirect)
|
||||
{matrix+=-this.edges[j].weight;}
|
||||
else
|
||||
{matrix+="0";}
|
||||
if(j!=this.edges.length-1)
|
||||
{matrix+=", ";}}
|
||||
matrix=matrix+"\n";}
|
||||
return matrix;}
|
||||
Graph.prototype.SplitMatrixString=function(line,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var res=[];var i=0;var isZeroOneLine=true;for(i=0;i<line.length;i++)
|
||||
{if(line.charAt(i)!='0'&&line.charAt(i)!='1')
|
||||
{isZeroOneLine=false;break;}}
|
||||
if(!isZeroOneLine)
|
||||
{if(separator!=",")
|
||||
{line=line.replace(/,/g,".");}
|
||||
for(i=0;i<line.length;i++)
|
||||
{if(("0123456789.-e").indexOf(line.charAt(i))<0)
|
||||
{if(i>0)
|
||||
{res.push(line.substr(0,i));}
|
||||
if(i==0)
|
||||
{i=1;}
|
||||
line=line.substr(i,line.length-i);i=-1;}}
|
||||
if(line.length>0)
|
||||
{res.push(line);}}
|
||||
else
|
||||
{for(i=0;i<line.length;i++)
|
||||
{res.push(line.charAt(i));}}
|
||||
console.log(res);return res;}
|
||||
Graph.prototype.SaveToXML=function(additionalData)
|
||||
{var mainHeader="<?xml version=\"1.0\" encoding=\"UTF-8\"?><graphml>";var header="<graph id=\"Graph\" uidGraph=\""+this.uidGraph+"\""+" uidEdge=\""+this.uidEdge+"\">";var xmlBody="";for(var i=0;i<this.vertices.length;i++)
|
||||
{xmlBody=xmlBody+this.vertices[i].SaveToXML();}
|
||||
xmlBody=xmlBody+"";for(var i=0;i<this.edges.length;i++)
|
||||
{xmlBody=xmlBody+this.edges[i].SaveToXML();}
|
||||
xmlBody=xmlBody+"";additionalField="";if(additionalData.length>0)
|
||||
{additionalField="<additional data=\""+additionalData+"\"/>"}
|
||||
return mainHeader+header+xmlBody+"</graph>"+additionalField+"</graphml>";}
|
||||
Graph.prototype.LoadFromXML=function(xmlText,additionalData)
|
||||
{xmlDoc=$.parseXML(xmlText);var $xml=$(xmlDoc);$graphs=$xml.find("graph");var loadedGraphId=0;var loadedEdgeId=0;$graphs.each(function(){loadedGraphId=parseInt($(this).attr('uidGraph'));loadedEdgeId=parseInt($(this).attr('uidEdge'));});if(isNaN(loadedEdgeId))
|
||||
{loadedEdgeId=this.edgesOffset;}else if(loadedEdgeId<this.edgesOffset)
|
||||
{loadedEdgeId=this.edgesOffset;}
|
||||
this.uidGraph=loadedGraphId;this.uidEdge=loadedEdgeId;$nodes=$xml.find("node");var vertices=[];$nodes.each(function(){var vertex=new BaseVertex();vertex.LoadFromXML($(this));vertices.push(vertex);});this.vertices=vertices;$edges=$xml.find("edge");var edges=[];var graph=this;$edges.each(function(){var edge=new BaseEdge();edge.LoadFromXML($(this),graph);if(edge.id<graph.uidEdge){edge.id=graph.uidEdge;graph.uidEdge++;}
|
||||
edges.push(edge);});this.edges=edges;$additional=$xml.find("additional");if($additional.length!=0&&additionalData!=null)
|
||||
{additionalData["data"]=$additional.attr('data');}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.hasDirectEdge=function()
|
||||
{var res=false;for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.hasUndirectEdge=function()
|
||||
{var res=false;for(var i=0;i<this.edges.length;i++)
|
||||
{if(!this.edges[i].isDirect)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.hasEdges=function()
|
||||
{return this.edges.length>0;}
|
||||
Graph.prototype.clampPositions=function(viewportSize)
|
||||
{var diameter=(new VertexModel()).diameter;for(i=0;i<this.vertices.length;i++)
|
||||
{this.vertices[i].position.x=Math.min(Math.max(this.vertices[i].position.x,diameter),viewportSize.x-diameter);this.vertices[i].position.y=Math.min(Math.max(this.vertices[i].position.y,diameter),viewportSize.y-diameter);}}
|
||||
Graph.prototype.getGraphBBox=function(viewportSize)
|
||||
{var pointMin=new Point(1e5,1e5);var pointMax=new Point(-1e5,-1e5);var diameter=(new VertexModel()).diameter;for(i=0;i<this.vertices.length;i++)
|
||||
{var vertex=this.vertices[i];var factor=vertex.diameterFactor();var deltaVector=new Point(factor.x*diameter,factor.y*diameter);pointMin=pointMin.min(vertex.position.subtract(deltaVector));pointMax=pointMax.max(vertex.position.add(deltaVector));}
|
||||
var max_curve_length=32;for(i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if(edge.model.type==EdgeModels.curve)
|
||||
{var max_curve=edge.vertex2.position.subtract(edge.vertex1.position).length()/max_curve_length;for(j=0;j<max_curve;j++)
|
||||
{var point=edge.model.GetCurvePoint(edge.vertex1.position,edge.vertex2.position,j/max_curve);var deltaVector=new Point(max_curve_length,max_curve_length);pointMin=pointMin.min(point.subtract(deltaVector));pointMax=pointMax.max(point.add(deltaVector));}}}
|
||||
return new Rect(pointMin,pointMax);}
|
||||
Graph.prototype.hasPair=function(edge)
|
||||
{return this.FindPairFor(edge)!=null;}
|
||||
Graph.prototype.FindPairFor=function(edge)
|
||||
{var res=this.getNeighborEdges(edge);return res.length==1?res[0]:null;}
|
||||
Graph.prototype.getNeighborEdges=function(edge)
|
||||
{var res=[];for(var i=0;i<this.edges.length;i++)
|
||||
{var curEdge=this.edges[i];if(curEdge==edge)
|
||||
continue;if((curEdge.vertex1.id==edge.vertex1.id&&curEdge.vertex2.id==edge.vertex2.id)||(curEdge.vertex1.id==edge.vertex2.id&&curEdge.vertex2.id==edge.vertex1.id))
|
||||
{res.push(curEdge);}}
|
||||
return res;}
|
||||
Graph.prototype.checkMutiGraph=function()
|
||||
{var res=false;var start={};for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if(start.hasOwnProperty(edge.vertex1.id)&&start[edge.vertex1.id]==edge.vertex2.id)
|
||||
{res=true;break;}
|
||||
start[edge.vertex1.id]=edge.vertex2.id;if(!edge.isDirect)
|
||||
{if(start.hasOwnProperty(edge.vertex2.id)&&start[edge.vertex2.id]==edge.vertex1.id)
|
||||
{res=true;break;}
|
||||
start[edge.vertex2.id]=edge.vertex1.id;}}
|
||||
return res;}
|
||||
Graph.prototype.isMulti=function()
|
||||
{return this.isMultiGraph;}
|
||||
Graph.prototype.isNeedReposition=function()
|
||||
{var res=false;for(var i=0;i<this.vertices.length;i++)
|
||||
{res=res||this.vertices[i].IsUndefinedPosition();}
|
||||
return res;}
|
||||
Graph.prototype.FixEdgeCurve=function(edgeIndex)
|
||||
{var edgeObject=this.edges[edgeIndex];var hasPair=this.hasPair(edgeObject);var neighborEdges=this.getNeighborEdges(edgeObject);if(hasPair)
|
||||
{if(edgeObject.model.default)
|
||||
edgeObject.model.type=EdgeModels.curve;var pairEdge=this.FindPairFor(edgeObject);if(pairEdge.model.default)
|
||||
{pairEdge.model.type=EdgeModels.curve;if(pairEdge.vertex1==edgeObject.vertex1&&pairEdge.vertex2==edgeObject.vertex2)
|
||||
pairEdge.model.curveValue=-pairEdge.model.curveValue;}}
|
||||
else if(neighborEdges.length>=2)
|
||||
{var curve=this.GetAvailableCurveValue(neighborEdges,edgeObject);if(edgeObject.model.default)
|
||||
{edgeObject.model.type=EdgeModels.curve;edgeObject.model.curveValue=curve;}}}
|
||||
Graph.prototype.GetAvailableCurveValue=function(neighborEdges,originalEdge)
|
||||
{var values=[];for(var i=0;i<neighborEdges.length;i++)
|
||||
{var edge=neighborEdges[i];var sameDirection=(originalEdge.vertex1.id==edge.vertex1.id);if(edge.model.type==EdgeModels.curve)
|
||||
{values[(sameDirection?edge.model.curveValue:-edge.model.curveValue)]=true;}}
|
||||
var changeValue=DefaultHandler.prototype.curveValue;var defaultValue=0.0;var maxSearch=10;for(var i=1;i<maxSearch;i++)
|
||||
{value=i*changeValue;if(!values.hasOwnProperty(value))
|
||||
return value;value=-i*changeValue;if(!values.hasOwnProperty(value))
|
||||
return value;}
|
||||
return defaultValue;}
|
||||
Graph.prototype.reverseAllEdges=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{let v1=this.edges[i].vertex1;this.edges[i].vertex1=this.edges[i].vertex2;this.edges[i].vertex2=v1;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.makeAllEdgesDirected=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(!this.edges[i].isDirect)
|
||||
{this.edges[i].isDirect=true;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.makeAllEdgesUndirected=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{this.edges[i].isDirect=false;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
moduleLoader.endCacheLoading();
|
13
script/pages/create_graph_by_matrix/api/index.js
Normal file
13
script/pages/create_graph_by_matrix/api/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
// Global version needs to force reload scripts from server.
|
||||
globalVersion = 75;
|
||||
|
||||
{
|
||||
let modulDir = "pages/create_graph_by_matrix/";
|
||||
|
||||
doInclude ([
|
||||
include ("entities/graph/api/index.js"),
|
||||
include ("model/createByMatrixMain.js", modulDir),
|
||||
include ("model/main.js", modulDir)
|
||||
]);
|
||||
}
|
670
script/pages/create_graph_by_matrix/api/index.js.cache
Normal file
670
script/pages/create_graph_by_matrix/api/index.js.cache
Normal file
@ -0,0 +1,670 @@
|
||||
moduleLoader.beginCacheLoading(["/script/entities/graph/api/index.js?v=75","/script/shared/point.js?v=75","/script/entities/edge/api/index.js?v=75","/script/entities/edge/model/BaseEdge.js?v=75","/script/entities/edge/model/EdgeModel.js?v=75","/script/entities/vertex/api/index.js?v=75","/script/entities/vertex/model/BaseVertex.js?v=75","/script/entities/vertex/model/VertexModel.js?v=75","/script/entities/graph/model/Graph.js?v=75","/script/pages/create_graph_by_matrix/model/createByMatrixMain.js?v=75","/script/pages/create_graph_by_matrix/model/main.js?v=75",]);globalVersion=75;{let modulDir="pages/create_graph_by_matrix/";doInclude([include("entities/graph/api/index.js"),include("model/createByMatrixMain.js",modulDir),include("model/main.js",modulDir)]);}
|
||||
{let modulDir="entities/graph/";doInclude([include("shared/point.js"),include("entities/edge/api/index.js"),include("entities/vertex/api/index.js"),include("model/Graph.js",modulDir)])}function Point(x,y){this.x=x||0;this.y=y||0;};Point.prototype.x=null;Point.prototype.y=null;Point.prototype.add=function(v){return new Point(this.x+v.x,this.y+v.y);};Point.prototype.addValue=function(v){return new Point(this.x+v,this.y+v);};Point.prototype.clone=function(){return new Point(this.x,this.y);};Point.prototype.degreesTo=function(v){var dx=this.x-v.x;var dy=this.y-v.y;var angle=Math.atan2(dy,dx);return angle*(180/Math.PI);};Point.prototype.distance=function(v){return Math.sqrt(this.distanceSqr(v));};Point.prototype.distanceSqr=function(v){var x=this.x-v.x;var y=this.y-v.y;return x*x+y*y;};Point.prototype.equals=function(toCompare){return this.x==toCompare.x&&this.y==toCompare.y;};Point.prototype.interpolate=function(v,f){return new Point((this.x+v.x)*f,(this.y+v.y)*f);};Point.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};Point.prototype.normalize=function(thickness){var l=this.length();this.x=this.x/l*thickness;this.y=this.y/l*thickness;return new Point(this.x,this.y);};Point.prototype.normalizeCopy=function(thickness){var l=this.length();return new Point(this.x/l*thickness,this.y/l*thickness);};Point.prototype.orbit=function(origin,arcWidth,arcHeight,degrees){var radians=degrees*(Math.PI/180);this.x=origin.x+arcWidth*Math.cos(radians);this.y=origin.y+arcHeight*Math.sin(radians);};Point.prototype.rotate=function(center,degrees){var radians=degrees*(Math.PI/180);offset=this.subtract(center);this.x=offset.x*Math.cos(radians)-offset.y*Math.sin(radians);this.y=offset.x*Math.sin(radians)+offset.y*Math.cos(radians);this.x=this.x+center.x;this.y=this.y+center.y;return this;};Point.prototype.offset=function(dx,dy){this.x+=dx;this.y+=dy;};Point.prototype.subtract=function(v){return new Point(this.x-v.x,this.y-v.y);};Point.prototype.subtractValue=function(value){return new Point(this.x-value,this.y-value);};Point.prototype.multiply=function(value){return new Point(this.x*value,this.y*value);};Point.prototype.toString=function(){return"(x="+this.x+", y="+this.y+")";};Point.prototype.normal=function(){return new Point(-this.y,this.x);};Point.prototype.min=function(point)
|
||||
{return new Point(Math.min(this.x,point.x),Math.min(this.y,point.y));};Point.prototype.max=function(point)
|
||||
{return new Point(Math.max(this.x,point.x),Math.max(this.y,point.y));};Point.prototype.inverse=function()
|
||||
{return new Point(-this.x,-this.y);};Point.prototype.cross=function(point)
|
||||
{return this.x*point.y-this.y*point.x;};Point.interpolate=function(pt1,pt2,f){return new Point(pt1.x*(1.0-f)+pt2.x*f,pt1.y*(1.0-f)+pt2.y*f);};Point.polar=function(len,angle){return new Point(len*Math.cos(angle),len*Math.sin(angle));};Point.distance=function(pt1,pt2){var x=pt1.x-pt2.x;var y=pt1.y-pt2.y;return Math.sqrt(x*x+y*y);};Point.center=function(pt1,pt2){return new Point((pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0);};Point.toString=function(){return x+" "+y;}
|
||||
Point.projection=function(point,line1,line2)
|
||||
{var x=line2.y-line1.y;var y=line1.x-line2.x;var l=(line1.cross(line2)+line1.cross(point)+line2.cross(point))/(x*(line2.y-line1.y)+y*(line1.x-line2.x));var res=new Point(point.x+x*l,point.y+y*l);return res;}
|
||||
Point.hitTest=function(pt11,pt12,pt21,pt22)
|
||||
{var res=null;var n=0.0;var x1=pt11.x;var y1=pt11.y;var x2=pt12.x;var y2=pt12.y;var x3=pt21.x;var y3=pt21.y;var x4=pt22.x;var y4=pt22.y;if(y2-y1!=0.0)
|
||||
{var q=(x2-x1)/(y1-y2);var sn=(x3-x4)+(y3-y4)*q;if(sn==0.0)
|
||||
{return res;}
|
||||
var fn=(x3-x1)+(y3-y1)*q;n=fn/sn;}
|
||||
else
|
||||
{if((y3-y4)==0.0)
|
||||
{return res;}
|
||||
n=(y3-y1)/(y3-y4);}
|
||||
res=new Point(x3+(x4-x3)*n,y3+(y4-y3)*n);var epsilon=1E-5;if(!(res.x>=Math.min(x1,x2)-epsilon&&res.x>=Math.min(x3,x4)-epsilon&&res.x<=Math.max(x1,x2)+epsilon&&res.x<=Math.max(x3,x4)+epsilon&&res.y>=Math.min(y1,y2)-epsilon&&res.y>=Math.min(y3,y4)-epsilon&&res.y<=Math.max(y1,y2)+epsilon&&res.y<=Math.max(y3,y4)+epsilon))
|
||||
{res=null;}
|
||||
return res;}
|
||||
function Rect(minPoint,maxPoint){this.minPoint=minPoint;this.maxPoint=maxPoint;};Rect.prototype.center=function()
|
||||
{return Point.center(this.minPoint,this.maxPoint);};Rect.prototype.size=function()
|
||||
{return this.maxPoint.subtract(this.minPoint);};Rect.prototype.left=function()
|
||||
{return this.minPoint.x;};Rect.prototype.top=function()
|
||||
{return this.minPoint.y;};Rect.prototype.isIn=function(v)
|
||||
{return this.minPoint.x<=v.x&&this.minPoint.y<=v.y&&this.maxPoint.x>v.x&&this.maxPoint.y>v.y;};{let modulDir="entities/edge/";doInclude([include("model/BaseEdge.js",modulDir),include("model/EdgeModel.js",modulDir)])}
|
||||
function BaseEdge(vertex1,vertex2,isDirect,weight,upText)
|
||||
{this.vertex1=vertex1;this.vertex2=vertex2;this.arrayStyleStart="";this.arrayStyleFinish="";this.isDirect=isDirect;this.weight=0;this.text="";this.useWeight=false;this.id=0;this.model=new EdgeModel();if(upText===undefined)
|
||||
this.upText="";else
|
||||
this.upText=upText;if(weight!==undefined)
|
||||
this.SetWeight(weight);this.ownStyles={};}
|
||||
BaseEdge.prototype.copyFrom=function(other)
|
||||
{this.vertex1=other.vertex1;this.vertex2=other.vertex2;this.arrayStyleStart=other.arrayStyleStart;this.arrayStyleFinish=other.arrayStyleFinish;this.isDirect=other.isDirect;this.weight=other.weight;this.text=other.text;this.useWeight=other.useWeight;this.id=other.id;this.model=new EdgeModel();this.model.copyFrom(other.model);this.upText=other.upText;this.ownStyles=FullObjectCopy(other.ownStyles);}
|
||||
BaseEdge.prototype.SaveToXML=function()
|
||||
{return"<edge "+"source=\""+this.vertex1.id+"\" "+"target=\""+this.vertex2.id+"\" "+"isDirect=\""+this.isDirect+"\" "+"weight=\""+this.weight+"\" "+"useWeight=\""+this.useWeight+"\" "+"id=\""+this.id+"\" "+"text=\""+gEncodeToHTML(this.text)+"\" "+"upText=\""+gEncodeToHTML(this.upText)+"\" "+"arrayStyleStart=\""+this.arrayStyleStart+"\" "+"arrayStyleFinish=\""+this.arrayStyleFinish+"\" "+
|
||||
((Object.keys(this.ownStyles).length>0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+
|
||||
this.model.SaveToXML()+"></edge>";}
|
||||
BaseEdge.prototype.LoadFromXML=function(xml,graph)
|
||||
{var attr=xml.attr('vertex1');if(typeof attr==='undefined')
|
||||
{attr=xml.attr('source');}
|
||||
this.vertex1=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph1'));var attr=xml.attr('vertex2');if(typeof attr==='undefined')
|
||||
{attr=xml.attr('target');}
|
||||
this.vertex2=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph2'));this.isDirect=xml.attr('isDirect')=="true";this.weight=parseFloat(xml.attr('weight'));if(isNaN(this.weight))
|
||||
{this.weight=1;}
|
||||
this.hasPair=xml.attr('hasPair')=="true";this.useWeight=xml.attr('useWeight')=="true";this.id=xml.attr('id');this.text=xml.attr("text")==null?"":gDecodeFromHTML(xml.attr("text"));this.arrayStyleStart=xml.attr("arrayStyleStart")==null?"":xml.attr("arrayStyleStart");this.arrayStyleFinish=xml.attr("arrayStyleFinish")==null?"":xml.attr("arrayStyleFinish");this.upText=xml.attr('upText');if(typeof this.upText==='undefined')
|
||||
{this.upText="";}
|
||||
else
|
||||
{this.upText=gDecodeFromHTML(this.upText);}
|
||||
var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined')
|
||||
{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave)
|
||||
{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField])
|
||||
{if(this.ownStyles[index].ShouldLoad(field))
|
||||
this.ownStyles[index][field]=parsedSave[indexField][field];}}}
|
||||
this.model.LoadFromXML(xml);}
|
||||
BaseEdge.prototype.GetPixelLength=function()
|
||||
{if(this.vertex1==this.vertex2)
|
||||
{return this.model.GetLoopSize()*2*Math.PI;}
|
||||
else
|
||||
{return Point.distance(this.vertex1.position,this.vertex2.position);}}
|
||||
BaseEdge.prototype.GetWeight=function()
|
||||
{return this.useWeight?this.weight:1;}
|
||||
BaseEdge.prototype.GetText=function()
|
||||
{return this.text.length>0?this.text:(this.useWeight?this.weight.toString():"");}
|
||||
BaseEdge.prototype.GetUpText=function()
|
||||
{return this.upText;}
|
||||
BaseEdge.prototype.GetStartEdgeStyle=function()
|
||||
{return this.arrayStyleStart;}
|
||||
BaseEdge.prototype.GetFinishEdgeStyle=function()
|
||||
{return(this.arrayStyleFinish!=""?this.arrayStyleFinish:(this.isDirect?"arrow":""));}
|
||||
BaseEdge.prototype.HitTest=function(pos)
|
||||
{var positions=this.GetEdgePositionsShift();return this.model.HitTest(positions[0],positions[1],pos);}
|
||||
BaseEdge.prototype.GetEdgePositionsShift=function()
|
||||
{return this.GetEdgePositions();}
|
||||
BaseEdge.prototype.GetEdgePositions=function()
|
||||
{var res=[];if(this.vertex1==this.vertex2)
|
||||
{res.push(this.vertex1.position);res.push(this.vertex2.position);return res;}
|
||||
var position1=this.vertex1.position;var position2=this.vertex2.position;var diameter1=this.vertex1.model.diameter+parseInt(this.vertex1.currentStyle.GetStyle({},this.vertex1).lineWidth);var diameter2=this.vertex2.model.diameter+parseInt(this.vertex2.currentStyle.GetStyle({},this.vertex2).lineWidth);var direction=position1.subtract(position2);var direction1=direction;var direction2=direction;var d1=diameter1;var d2=diameter2;if(this.model.type==EdgeModels.curve)
|
||||
{var dist=position1.distance(position2);var point1=this.model.GetCurvePoint(position1,position2,10.0/dist);direction1=position1.subtract(point1);var point2=this.model.GetCurvePoint(position1,position2,1.0-10.0/dist);direction2=position2.subtract(point2);d2=diameter2;}
|
||||
else
|
||||
{direction2=direction2.multiply(-1);}
|
||||
direction1.normalize(1.0);direction2.normalize(1.0);var vertices=[];vertices.push({vertex:this.vertex1,direction:direction1,position:position1,diameter:d1});vertices.push({vertex:this.vertex2,direction:direction2,position:position2,diameter:d2});vertices.forEach(function(data)
|
||||
{var shape=data.vertex.currentStyle.GetStyle({},data.vertex).shape;if(shape==VertexCircleShape)
|
||||
{var direction=data.direction.multiply(0.5);res.push(data.position.subtract(direction.multiply(data.diameter)));}
|
||||
else
|
||||
{var lineFinish1=data.direction.multiply(-1).multiply(1000.0);var pointsVertex1=GetPointsForShape(shape,data.diameter,data.vertex.mainText);pointsVertex1.push(pointsVertex1[0]);for(var i=0;i<pointsVertex1.length-1;i++)
|
||||
{var hitText=Point.hitTest(new Point(0,0),lineFinish1,pointsVertex1[i],pointsVertex1[i+1]);if(hitText!=null)
|
||||
{res.push(data.position.add(hitText));break;}}}});return res;}
|
||||
BaseEdge.prototype.SetWeight=function(weight)
|
||||
{var useWeight=false;if(!isNaN(parseInt(weight,10)))
|
||||
{useWeight=true;}
|
||||
weight=(!isNaN(parseInt(weight,10))&&weight>=0)?weight:1;this.weight=Number(weight);this.useWeight=useWeight;}
|
||||
BaseEdge.prototype.SetUpText=function(text)
|
||||
{this.upText=text;}
|
||||
BaseEdge.prototype.resetOwnStyle=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{delete this.ownStyles[index];}}
|
||||
BaseEdge.prototype.setOwnStyle=function(index,style)
|
||||
{this.ownStyles[index]=style;}
|
||||
BaseEdge.prototype.getStyleFor=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{return this.ownStyles[index];}
|
||||
else
|
||||
{var style=null;if(index==0)
|
||||
style=globalApplication.GetStyle("edge","common");else
|
||||
style=globalApplication.GetStyle("edge","selected",undefined,index-1);return style;}}
|
||||
BaseEdge.prototype.hasOwnStyleFor=function(index)
|
||||
{return this.ownStyles.hasOwnProperty(index);}
|
||||
var EdgeModels={"line":0,"curve":1};const defaultEdgeWidth=4;function EdgeModel()
|
||||
{this.width=globalApplication.GetDefaultEdgeWidth();this.type=EdgeModels.line;this.curveValue=EdgeModel.prototype.defaultCurve;this.default=true;this.sizeOfLoop=24;this.loopShiftAngel=Math.PI/6;}
|
||||
EdgeModel.prototype.defaultCurve=0.1;EdgeModel.prototype.copyFrom=function(other)
|
||||
{this.width=other.width;this.type=other.type;this.curveValue=other.curveValue;this.default=other.default;}
|
||||
EdgeModel.prototype.SaveToXML=function()
|
||||
{return"model_width=\""+this.width+"\" "+"model_type=\""+this.type+"\" "+"model_curveValue=\""+this.curveValue+"\" "+"model_default=\""+this.default+"\" ";}
|
||||
EdgeModel.prototype.LoadFromXML=function(xml,graph)
|
||||
{this.width=xml.attr('model_width')==null?this.width:parseFloat(xml.attr("model_width"));this.type=xml.attr('model_type')==null?this.type:xml.attr("model_type");this.curveValue=xml.attr('model_curveValue')==null?this.curveValue:parseFloat(xml.attr("model_curveValue"));this.default=xml.attr('model_default')==null?this.default:parseFloat(xml.attr("model_default"));}
|
||||
EdgeModel.prototype.GetCurvePoint=function(position1,position2,t)
|
||||
{var points=this.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];var B0_t=Math.pow(1-t,3);var B1_t=3*t*Math.pow(1-t,2);var B2_t=3*t*t*(1-t)
|
||||
var B3_t=t*t*t;var ax=position1.x;var ay=position1.y;var dx=position2.x;var dy=position2.y;var bx=firstBezierPoint.x;var by=firstBezierPoint.y;var cx=secondBezierPoint.x;var cy=secondBezierPoint.y;var px_t=(B0_t*ax)+(B1_t*bx)+(B2_t*cx)+(B3_t*dx);var py_t=(B0_t*ay)+(B1_t*by)+(B2_t*cy)+(B3_t*dy);return new Point(px_t,py_t);}
|
||||
EdgeModel.prototype.GetBezierPoints=function(position1,position2)
|
||||
{var direction=position2.subtract(position1);var delta=direction.length();direction.normalize(1.0);var normal=direction.normal();var deltaOffsetPixels=delta*this.curveValue;var yOffset=normal.multiply(deltaOffsetPixels);var firstBezierPointShift=(direction.multiply(delta*0.2)).add(yOffset);var secondBezierPointShift=(direction.multiply(-delta*0.2)).add(yOffset);var firstBezierPoint=position1.add(firstBezierPointShift);var secondBezierPoint=position2.add(secondBezierPointShift);return[firstBezierPoint,secondBezierPoint];}
|
||||
EdgeModel.prototype.HitTest=function(position1,position2,mousePos)
|
||||
{if(this.type==EdgeModels.line)
|
||||
return this.HitTestLine(position1,position2,mousePos);else if(this.type==EdgeModels.curve)
|
||||
return this.HitTestCurve(position1,position2,mousePos);return false;}
|
||||
EdgeModel.prototype.HitTestLine=function(position1,position2,mousePos,factor)
|
||||
{if(factor===undefined)
|
||||
{factor=1.0;}
|
||||
var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2))
|
||||
{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5*factor;}
|
||||
var r1=pos0.distance(pos1);var r2=pos0.distance(pos2);var r12=pos1.distance(pos2);if(r1>=(new Point(r2,r12)).length()||r2>=(new Point(r1,r12)).length())
|
||||
{}
|
||||
else
|
||||
{var distance=((pos1.y-pos2.y)*pos0.x+(pos2.x-pos1.x)*pos0.y+(pos1.x*pos2.y-pos2.x*pos1.y))/r12;if(Math.abs(distance)<=this.width*1.5*factor)
|
||||
{return true;}}
|
||||
return false;}
|
||||
EdgeModel.prototype.HitTestCurve=function(position1,position2,mousePos)
|
||||
{var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2))
|
||||
{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5;}
|
||||
var interval_count=position1.distance(position2)/100*30;var start=position1;for(var i=0;i<interval_count;i++)
|
||||
{var finish=this.GetCurvePoint(position1,position2,i/interval_count);if(this.HitTestLine(start,finish,mousePos,2.0))
|
||||
return true;start=finish;}
|
||||
return false;}
|
||||
EdgeModel.prototype.ChangeCurveValue=function(delta)
|
||||
{if(this.type==EdgeModels.line)
|
||||
{this.type=EdgeModels.curve;this.curveValue=0.0;}
|
||||
this.curveValue=this.curveValue+delta;if(Math.abs(this.curveValue)<=0.01)
|
||||
this.type=EdgeModels.line;this.default=false;}
|
||||
EdgeModel.prototype.SetCurveValue=function(value)
|
||||
{if(this.type==EdgeModels.line)
|
||||
{this.type=EdgeModels.curve;this.curveValue=0.0;}
|
||||
this.curveValue=value;if(Math.abs(this.curveValue)<=0.01)
|
||||
this.type=EdgeModels.line;this.default=false;}
|
||||
EdgeModel.prototype.GetLoopSize=function()
|
||||
{if(Math.abs(this.curveValue)<=0.01)
|
||||
{return this.sizeOfLoop;}
|
||||
else
|
||||
{let normalCurve=this.curveValue;if(this.type==EdgeModels.line){normalCurve=this.defaultCurve;}
|
||||
else if(normalCurve>=0.0){normalCurve+=this.defaultCurve}
|
||||
return this.sizeOfLoop*Math.abs(normalCurve)*(1/this.defaultCurve);}}
|
||||
EdgeModel.prototype.GetLoopShiftAngel=function()
|
||||
{if(this.type==EdgeModels.line||this.curveValue>=0.0)
|
||||
{return this.loopShiftAngel;}
|
||||
else
|
||||
{return this.loopShiftAngel+Math.PI;}}
|
||||
{let modulDir="entities/vertex/";doInclude([include("model/BaseVertex.js",modulDir),include("model/VertexModel.js",modulDir)])}
|
||||
function BaseVertex(x,y,vertexEnumType)
|
||||
{this.position=new Point(x,y);this.id=0;this.mainText="";this.upText="";this.vertexEnumType=vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=false;this.ownStyles={};};BaseVertex.prototype.position=new Point(0,0);BaseVertex.prototype.copyFrom=function(other)
|
||||
{this.position=new Point(other.position.x,other.position.y);this.id=other.id;this.mainText=other.mainText;this.upText=other.upText;this.vertexEnumType=other.vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=other.hasUndefinedPosition;this.ownStyles=FullObjectCopy(other.ownStyles);}
|
||||
BaseVertex.prototype.SaveToXML=function()
|
||||
{return"<node "+"positionX=\""+this.position.x+"\" "+"positionY=\""+this.position.y+"\" "+"id=\""+this.id+"\" "+"mainText=\""+gEncodeToHTML(this.mainText)+"\" "+"upText=\""+gEncodeToHTML(this.upText)+"\" "+
|
||||
((Object.keys(this.ownStyles).length>0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+"size=\""+this.model.diameter+"\" "+"></node>";}
|
||||
BaseVertex.prototype.LoadFromXML=function(xml)
|
||||
{var xmlX=xml.attr('positionX');var xmlY=xml.attr('positionY');this.hasUndefinedPosition=(typeof xmlX==='undefined')||(typeof xmlY==='undefined');this.position=new Point(parseFloat(xmlX),parseFloat(xmlY));this.id=xml.attr('id');this.mainText=xml.attr('mainText');this.upText=xml.attr('upText');if(typeof this.mainText==='undefined')
|
||||
this.mainText=this.id;else
|
||||
this.mainText=gDecodeFromHTML(this.mainText);if(typeof this.upText==='undefined')
|
||||
this.upText="";else
|
||||
this.upText=gDecodeFromHTML(this.upText);var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined')
|
||||
{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave)
|
||||
{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField])
|
||||
{if(this.ownStyles[index].ShouldLoad(field))
|
||||
this.ownStyles[index][field]=parsedSave[indexField][field];}}}
|
||||
var size=xml.attr('size');if(typeof size!=='undefined')
|
||||
this.model.diameter=parseInt(size);}
|
||||
BaseVertex.prototype.SetId=function(id)
|
||||
{this.id=id;if(this.vertexEnumType!=null)
|
||||
this.mainText=this.vertexEnumType.GetVertexText(id);}
|
||||
BaseVertex.prototype.diameterFactor=function()
|
||||
{return new Point(1.0+(this.mainText.length?this.mainText.length/8.0:0),1.5);}
|
||||
BaseVertex.prototype.IsUndefinedPosition=function()
|
||||
{return this.hasUndefinedPosition;}
|
||||
BaseVertex.prototype.HitTest=function(pos)
|
||||
{var shape=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).shape:VertexCircleShape;var width=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).lineWidth:0;if(shape==VertexCircleShape)
|
||||
{return this.position.distance(pos)<this.model.diameter/2.0+width;}
|
||||
else
|
||||
{var relativePos=(new Point(pos.x,pos.y)).subtract(this.position);var lineFinish1=relativePos.add(new Point(1000,0));var lineFinish2=relativePos.add(new Point(-1000,0));var pointsVertex1=GetPointsForShape(shape,this.model.diameter+width,this.mainText);pointsVertex1.push(pointsVertex1[0]);var hitNumber1=0;var hitNumber2=0;for(var i=0;i<pointsVertex1.length-1;i++)
|
||||
{var hitTest=Point.hitTest(relativePos,lineFinish1,pointsVertex1[i],pointsVertex1[i+1]);if(hitTest!=null)
|
||||
{hitNumber1++;}
|
||||
hitTest=Point.hitTest(relativePos,lineFinish2,pointsVertex1[i],pointsVertex1[i+1]);if(hitTest!=null)
|
||||
{hitNumber2++;}}
|
||||
return hitNumber1==1&&hitNumber2==1;}
|
||||
return false;}
|
||||
BaseVertex.prototype.resetOwnStyle=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{delete this.ownStyles[index];}}
|
||||
BaseVertex.prototype.setOwnStyle=function(index,style)
|
||||
{this.ownStyles[index]=FullObjectCopy(style);}
|
||||
BaseVertex.prototype.getStyleFor=function(index)
|
||||
{if(this.ownStyles.hasOwnProperty(index))
|
||||
{return this.ownStyles[index];}
|
||||
else
|
||||
{var style=null;if(index==0)
|
||||
style=globalApplication.GetStyle("vertex","common");else
|
||||
style=globalApplication.GetStyle("vertex","selected",undefined,index-1);return style;}}
|
||||
BaseVertex.prototype.hasOwnStyleFor=function(index)
|
||||
{return this.ownStyles.hasOwnProperty(index);}
|
||||
const defaultVertexDiameter=30;function VertexModel()
|
||||
{this.diameter=globalApplication.GetDefaultVertexSize();}
|
||||
function Graph()
|
||||
{this.vertices=[];this.edges=[];this.uidGraph=0;this.uidEdge=10000;this.hasDirect=false;this.isMultiGraph=false;};Graph.prototype.infinity=1E8;Graph.prototype.maxVertices=1000;Graph.prototype.edgesOffset=10000;Graph.prototype.AddNewVertex=function(vertex)
|
||||
{if(this.vertices.length<=this.maxVertices)
|
||||
{vertex.SetId(this.uidGraph);this.uidGraph=this.uidGraph+1;this.vertices.push(vertex);}
|
||||
return this.vertices.length-1;}
|
||||
Graph.prototype.ClearGraph=function(){this.vertices=[];this.edges=[];this.uidGraph=0;this.uidEdge=10000;this.hasDirect=false;this.isMultiGraph=false;}
|
||||
Graph.prototype.AddNewEdgeSafe=function(graph1,graph2,isDirect,weight,replaceIfExists=true)
|
||||
{return this.AddNewEdge(new BaseEdge(graph1,graph2,isDirect,weight),replaceIfExists);}
|
||||
Graph.prototype.AddNewEdge=function(edge,replaceIfExists)
|
||||
{edge.id=this.uidEdge;this.uidEdge=this.uidEdge+1;var edge1=this.FindEdgeAny(edge.vertex1.id,edge.vertex2.id);var edgeRevert=this.FindEdgeAny(edge.vertex2.id,edge.vertex1.id);if(!edge.isDirect)
|
||||
{if(edge1!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edge1);if(edgeRevert!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edgeRevert);this.edges.push(edge);}
|
||||
else
|
||||
{if(edge1!=null&&replaceIfExists)
|
||||
this.DeleteEdge(edge1);if(edgeRevert!=null&&!edgeRevert.isDirect&&replaceIfExists)
|
||||
this.DeleteEdge(edgeRevert);this.edges.push(edge);}
|
||||
this.isMultiGraph=this.checkMutiGraph();return this.edges.length-1;}
|
||||
Graph.prototype.DeleteEdge=function(edgeObject)
|
||||
{var index=this.edges.indexOf(edgeObject);if(index>-1)
|
||||
{this.edges.splice(index,1);}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.DeleteVertex=function(vertexObject)
|
||||
{var index=this.vertices.indexOf(vertexObject);if(index>-1)
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].vertex1==vertexObject||this.edges[i].vertex2==vertexObject)
|
||||
{this.DeleteEdge(this.edges[i]);i--;}}
|
||||
this.vertices.splice(index,1);}}
|
||||
Graph.prototype.HasConnectedNodes=function(vertexObject)
|
||||
{var res=false;var index=this.vertices.indexOf(vertexObject);if(index>-1)
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].vertex1==vertexObject||this.edges[i].vertex2==vertexObject)
|
||||
{res=true;break;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindVertex=function(id)
|
||||
{var res=null;for(var i=0;i<this.vertices.length;i++)
|
||||
{if(this.vertices[i].id==id)
|
||||
{res=this.vertices[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindVertexByTitle=function(title)
|
||||
{var res=null;for(var i=0;i<this.vertices.length;i++)
|
||||
{if(this.vertices[i].mainText==title)
|
||||
{res=this.vertices[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdge=function(id1,id2)
|
||||
{return this.FindEdgeAny(id1,id2);}
|
||||
Graph.prototype.FindEdgeById=function(edgeId)
|
||||
{var res=null;for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].id==edgeId)
|
||||
{res=this.edges[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeAny=function(id1,id2)
|
||||
{var res=null;for(var i=0;i<this.edges.length;i++)
|
||||
{if((this.edges[i].vertex1.id==id1&&this.edges[i].vertex2.id==id2)||(!this.edges[i].isDirect&&this.edges[i].vertex1.id==id2&&this.edges[i].vertex2.id==id1))
|
||||
{res=this.edges[i];break;}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMin=function(id1,id2)
|
||||
{var res=null;var minWeight=this.infinity;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight<minWeight)
|
||||
{res=edge;minWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMax=function(id1,id2)
|
||||
{var res=null;var maxWeight=0;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight>maxWeight)
|
||||
{res=edge;maxWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindEdgeMinIgnoreDirection=function(id1,id2)
|
||||
{var res=null;var minWeight=this.infinity;for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{if(edge.weight<minWeight)
|
||||
{res=edge;minWeight=edge.weight;}}}
|
||||
return res;}
|
||||
Graph.prototype.FindAllEdges=function(id1,id2)
|
||||
{var res=[];for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if((edge.vertex1.id==id1&&edge.vertex2.id==id2)||(!edge.isDirect&&edge.vertex1.id==id2&&edge.vertex2.id==id1))
|
||||
{res.push(edge);}}
|
||||
return res;}
|
||||
Graph.prototype.GetAdjacencyMatrixStr=function()
|
||||
{var matrix="";for(var i=0;i<this.vertices.length;i++)
|
||||
{for(var j=0;j<this.vertices.length;j++)
|
||||
{var edge=this.FindEdgeMin(this.vertices[i].id,this.vertices[j].id);if(edge!=null)
|
||||
{matrix+=edge.weight;}
|
||||
else
|
||||
{matrix+="0";}
|
||||
if(j!=this.vertices.length)
|
||||
{matrix+=", ";}}
|
||||
matrix=matrix+"\n";}
|
||||
return matrix;}
|
||||
Graph.prototype.GetAdjacencyMatrix=function()
|
||||
{var matrix=[];for(var i=0;i<this.vertices.length;i++)
|
||||
{matrix.push([]);var v1=this.vertices[i];for(var j=0;j<this.vertices.length;j++)
|
||||
{var v2=this.vertices[j];var edge=this.FindEdgeMin(v1.id,v2.id);if(edge!=null)
|
||||
{matrix[i][j]=edge.GetWeight();}
|
||||
else
|
||||
{matrix[i][j]=this.infinity;}}}
|
||||
return matrix;}
|
||||
Graph.prototype.TestAdjacencyMatrix=function(matrix,rowsObj,colsObj,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j<rowsObj.rows.length;++j)
|
||||
{if(rowsObj.rows[j]==="")
|
||||
{rowsObj.rows.splice(j--,1);}}
|
||||
colsObj.cols=[];for(var i=0;i<rowsObj.rows.length;i++)
|
||||
{colsObj.cols[i]=this.SplitMatrixString(rowsObj.rows[i],separator);for(j=0;j<colsObj.cols[i].length;++j)
|
||||
{if(colsObj.cols[i][j]==="")
|
||||
{colsObj.cols[i].splice(j--,1);}}
|
||||
if(colsObj.cols[i].length!=rowsObj.rows.length)
|
||||
{bGoodFormat=false;break;}}
|
||||
return bGoodFormat;}
|
||||
Graph.prototype.TestPair=function(pair)
|
||||
{let lines=pair.split("\n");let regExp=[/^.+-.+$/g,/^.+\>.+$/g,/^.+<.+$/g,/^.+-\(\d+\.?\d+\)-.+$/g,/^.+-\(\d+\.?\d+\)\>.+$/g,/^.+<\(\d+\.?\d+\)\-.+$/g];let res=true;for(let i=0;i<lines.length;++i)
|
||||
{let resLine=false;let line=lines[i];if(line==""){continue;}
|
||||
for(let j=0;j<regExp.length;++j){if(line.match(regExp[j])){resLine=true;}}
|
||||
res=resLine&&res;}
|
||||
return res;}
|
||||
Graph.prototype.IsVerticesHaveSamePosition=function(position,vertexCount)
|
||||
{var res=false;for(var j=0;j<Math.min(this.vertices.length,vertexCount);j++)
|
||||
{if(position.distance(this.vertices[j].position)<this.vertices[j].model.diameter*2)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.GetRandomPosition=function(viewportSize){return new Point(Math.random()*viewportSize.x,Math.random()*viewportSize.y);}
|
||||
Graph.prototype.GetRandomPositionOfVertex=function(matrix,vertexIndex,viewportSize)
|
||||
{var point=new Point(0,0);var relatedVertex=[];for(var j=0;j<matrix.length;j++)
|
||||
{if(j<this.vertices.length&&(cols[vertexIndex][j]>0||cols[j][vertexIndex]>0)&&j!=vertexIndex)
|
||||
{relatedVertex.push(this.vertices[j]);}}
|
||||
var diameter=(new VertexModel()).diameter;if(relatedVertex.length>1)
|
||||
{for(var j=0;j<relatedVertex.length;j++)
|
||||
{point=point.add(relatedVertex[j].position);}
|
||||
point=point.multiply(1/relatedVertex.length);point.offset(Math.random()*diameter+(Math.random()?-1:1)*2*diameter,Math.random()*diameter+(Math.random()?-1:1)*2*diameter);}
|
||||
else
|
||||
{point=new Point(Math.random()*viewportSize.x,Math.random()*viewportSize.y);}
|
||||
if(this.IsVerticesHaveSamePosition(point,matrix.length))
|
||||
{point.offset(Math.random()*diameter+ +(Math.random()?-1:1)*4*diameter,Math.random()*diameter+ +(Math.random()?-1:1)*4*diameter);}
|
||||
point.x=Math.min(Math.max(point.x,diameter),viewportSize.x);point.y=Math.min(Math.max(point.y,diameter),viewportSize.y);return point;}
|
||||
Graph.prototype.VerticesReposition=function(viewportSize,newVertices)
|
||||
{var maxGravityDistanceSqr=Math.max(viewportSize.x,viewportSize.y)/5.0;maxGravityDistanceSqr=maxGravityDistanceSqr*maxGravityDistanceSqr;var velocityDamping=0.85;var diameter=(new VertexModel()).diameter;var maxDistance=diameter*3;var gravityDistanceSqr=10*(maxDistance*maxDistance);var edgeGravityKof=10/(maxDistance);var kCenterForce=10/(maxDistance*10);var centerPoint=viewportSize.multiply(0.5);var velocityMax=maxDistance*10;var edgesMatrix={};for(var i=0;i<this.edges.length;i++)
|
||||
{edgesMatrix[this.edges[i].vertex1.id+this.edges[i].vertex2.id*1000]=1;edgesMatrix[this.edges[i].vertex2.id+this.edges[i].vertex1.id*1000]=1;}
|
||||
var startAngel=Math.random()*180.0;for(i=0;i<newVertices.length;i++)
|
||||
{newVertices[i].position.orbit(new Point(viewportSize.x/2,viewportSize.y/2),(viewportSize.x-diameter*2)/2,(viewportSize.y-diameter*2)/2,360*i/newVertices.length+startAngel);}
|
||||
var k=0;var bChanged=true;while(k<1000&&bChanged)
|
||||
{var vertexData=[];for(i=0;i<newVertices.length;i++)
|
||||
{var currentVertex={};currentVertex.object=newVertices[i];currentVertex.net_force=new Point(0,0);currentVertex.velocity=new Point(0,0);vertexData.push(currentVertex);for(j=0;j<this.vertices.length;j++)
|
||||
{otherVertex=this.vertices[j];if(otherVertex==currentVertex.object)continue;var rsq=currentVertex.object.position.distanceSqr(otherVertex.position);{var force=(currentVertex.object.position.subtract(otherVertex.position)).normalize(gravityDistanceSqr/rsq);currentVertex.net_force=currentVertex.net_force.add(force);}}
|
||||
for(j=0;j<this.vertices.length;j++)
|
||||
{otherVertex=this.vertices[j];if(edgesMatrix.hasOwnProperty(currentVertex.object.id+1000*otherVertex.id))
|
||||
{var distance=currentVertex.object.position.distance(otherVertex.position);if(distance>maxDistance)
|
||||
{var force=(otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof*(distance-maxDistance));currentVertex.net_force=currentVertex.net_force.add(force);}}}
|
||||
var distanceToCenter=centerPoint.distance(currentVertex.object.position);var force=centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter*kCenterForce);currentVertex.net_force=currentVertex.net_force.add(force);currentVertex.velocity=currentVertex.velocity.add(currentVertex.net_force);}
|
||||
bChanged=false;for(i=0;i<vertexData.length;i++)
|
||||
{var v=vertexData[i];var velocity=v.velocity;if(velocity.length()>velocityMax)
|
||||
{velocity=velocity.normalize(velocityMax);}
|
||||
v.object.position=v.object.position.add(velocity);if(velocity.length()>=1)
|
||||
{bChanged=true;}}
|
||||
k++;}
|
||||
var bbox=this.getGraphBBox();if(bbox.size().length()>viewportSize.length()*1000)
|
||||
{for(i=0;i<newVertices.length;i++)
|
||||
{newVertices[i].position.orbit(new Point(viewportSize.x/2,viewportSize.y/2),(viewportSize.x-diameter*2)/2,(viewportSize.y-diameter*2)/2,360*i/newVertices.length+startAngel);}}
|
||||
else
|
||||
{var count=10;var angle=360.0/count;var viewportAspect=viewportSize.x/viewportSize.y;var bestIndex=0;var graphSize=bbox.size();var bestAspect=graphSize.x/graphSize.y;var center=bbox.center();for(var i=1;i<count;i++)
|
||||
{for(j=0;j<newVertices.length;j++)
|
||||
{newVertices[j].position.rotate(center,angle);}
|
||||
var newBBox=this.getGraphBBox();var newAspect=newBBox.size().x/newBBox.size().y;if(Math.abs(newAspect-viewportAspect)<Math.abs(bestAspect-viewportAspect))
|
||||
{bestAspect=newAspect;bestIndex=i;}}
|
||||
for(j=0;j<newVertices.length;j++)
|
||||
{newVertices[j].position.rotate(center,-angle*(count-bestIndex-1));}}}
|
||||
Graph.prototype.SetAdjacencyMatrix=function(matrix,viewportSize,currentEnumVerticesType,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var rowsObj={};var colsObj={};if(this.TestAdjacencyMatrix(matrix,rowsObj,colsObj,separator))
|
||||
{rows=rowsObj.rows;cols=colsObj.cols;var clonedEdge=this.edges.slice(0);for(var i=0;i<clonedEdge.length;i++)
|
||||
{this.DeleteEdge(clonedEdge[i]);}
|
||||
var newVertices=[];var bWeightGraph=false;for(var i=0;i<rows.length;i++)
|
||||
{for(var j=0;j<rows.length;j++)
|
||||
{if(j>=this.vertices.length)
|
||||
{var newPos=this.GetRandomPositionOfVertex(matrix,j,viewportSize);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);}
|
||||
if(cols[i][j]>0)
|
||||
{var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[i],this.vertices[j],cols[i][j]!=cols[j][i],cols[i][j],true);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0)
|
||||
{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
for(var i=rows.length;i<Math.max(this.vertices.length,rows.length);i++)
|
||||
{this.DeleteVertex(this.vertices[i]);i--;}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.SetPair=function(pairs,viewportSize,currentEnumVerticesType)
|
||||
{if(this.TestPair(pairs))
|
||||
{this.ClearGraph();let lines=pairs.split("\n");let regExp=[/^(.+)-(.+)$/g,/^(.+)\>(.+)$/g,/^(.+)<(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)-(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)\>(.+)$/g,/^(.+)<\((\d+|\d+\.?\d+)\)\-(.+)$/g,];let bWeightGraph=false;var newVertices=[];for(var i=0;i<lines.length;i++)
|
||||
{let line=lines[i];if(line==""){continue;}
|
||||
for(let j=regExp.length-1;j>=0;--j){if(!line.match(regExp[j])){continue;}
|
||||
let groupes=Array.from(line.matchAll(regExp[j]));let groupe=groupes[0];let vetext1Title=groupe[1];let vertex1=this.FindVertexByTitle(vetext1Title);if(vertex1==null){let newPosition=this.GetRandomPosition(viewportSize);vertex1=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex1.mainText=vetext1Title;newVertices.push(vertex1);}
|
||||
let vetext2Title=groupe[j<=2?2:3];let vertex2=this.FindVertexByTitle(vetext2Title);if(vertex2==null){let newPosition=this.GetRandomPosition(viewportSize);vertex2=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex2.mainText=vetext2Title;newVertices.push(vertex2);}
|
||||
let isDirect=j==1||j==2||j==4||j==5;let weight=1;if(j>2){weight=groupe[2];bWeightGraph=true;}
|
||||
let isRevertEdge=j==2||j==5;let nEdgeIndex=this.AddNewEdgeSafe(isRevertEdge?vertex2:vertex1,isRevertEdge?vertex1:vertex2,isDirect,weight,false);this.FixEdgeCurve(nEdgeIndex);break;}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j<rowsObj.rows.length;++j)
|
||||
{if(rowsObj.rows[j]==="")
|
||||
{rowsObj.rows.splice(j--,1);}}
|
||||
colsObj.cols=[];var columnCount=0;for(var i=0;i<rowsObj.rows.length;i++)
|
||||
{colsObj.cols[i]=this.SplitMatrixString(rowsObj.rows[i],separator);for(j=0;j<colsObj.cols[i].length;++j)
|
||||
{if(colsObj.cols[i][j]==="")
|
||||
{colsObj.cols[i].splice(j--,1);}}
|
||||
if(i==0)
|
||||
{columnCount=colsObj.cols[i].length;}
|
||||
if(colsObj.cols[i].length!=columnCount)
|
||||
{bGoodFormat=false;break;}}
|
||||
if(bGoodFormat)
|
||||
{for(var i=0;i<colsObj.cols[0].length;i++)
|
||||
{var values=[];for(j=0;j<colsObj.cols.length;++j)
|
||||
{if(colsObj.cols[j][i]!=0)
|
||||
{values.push(colsObj.cols[j][i]);}}
|
||||
if(!(values.length<=1||(values.length==2&&(values[0]==values[1]||values[0]==-values[1]))))
|
||||
{bGoodFormat=false;break;}}}
|
||||
return bGoodFormat;}
|
||||
Graph.prototype.SetIncidenceMatrix=function(matrix,viewportSize,currentEnumVerticesType)
|
||||
{var rowsObj={};var colsObj={};if(this.TestIncidenceMatrix(matrix,rowsObj,colsObj))
|
||||
{rows=rowsObj.rows;cols=colsObj.cols;var clonedEdge=this.edges.slice(0);for(var i=0;i<clonedEdge.length;i++)
|
||||
{this.DeleteEdge(clonedEdge[i]);}
|
||||
var newVertices=[];var bWeightGraph=false;for(var i=0;i<cols[0].length;i++)
|
||||
{var edgeValue=[];var edgeIndex=[];for(var j=0;j<cols.length;j++)
|
||||
{if(j>=this.vertices.length)
|
||||
{var newPos=new Point(0,0);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);}
|
||||
if(cols[j][i]!=0)
|
||||
{edgeValue.push(cols[j][i]);edgeIndex.push(j);}}
|
||||
if(edgeIndex.length==1)
|
||||
{edgeValue.push(edgeValue[0]);edgeIndex.push(edgeIndex[0]);}
|
||||
if(edgeIndex.length==2)
|
||||
{if(edgeValue[0]!=edgeValue[1])
|
||||
{if(edgeValue[1]>0)
|
||||
{edgeValue=edgeValue.swap(0,1);edgeIndex=edgeIndex.swap(0,1);}}
|
||||
var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[edgeIndex[0]],this.vertices[edgeIndex[1]],edgeValue[0]!=edgeValue[1],Math.abs(edgeValue[1]),false);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0)
|
||||
{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}
|
||||
if(!bWeightGraph)
|
||||
{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});}
|
||||
for(var i=cols.length;i<Math.max(this.vertices.length,cols.length);i++)
|
||||
{this.DeleteVertex(this.vertices[i]);i--;}
|
||||
this.VerticesReposition(viewportSize,newVertices);}}
|
||||
Graph.prototype.GetIncidenceMatrix=function()
|
||||
{var matrix="";for(var i=0;i<this.vertices.length;i++)
|
||||
{for(var j=0;j<this.edges.length;j++)
|
||||
{if(this.edges[j].vertex1==this.vertices[i])
|
||||
{matrix+=this.edges[j].weight;}
|
||||
else if(this.edges[j].vertex2==this.vertices[i]&&!this.edges[j].isDirect)
|
||||
{matrix+=this.edges[j].weight;}
|
||||
else if(this.edges[j].vertex2==this.vertices[i]&&this.edges[j].isDirect)
|
||||
{matrix+=-this.edges[j].weight;}
|
||||
else
|
||||
{matrix+="0";}
|
||||
if(j!=this.edges.length-1)
|
||||
{matrix+=", ";}}
|
||||
matrix=matrix+"\n";}
|
||||
return matrix;}
|
||||
Graph.prototype.SplitMatrixString=function(line,separator)
|
||||
{if(separator===undefined)
|
||||
{separator=",";}
|
||||
var res=[];var i=0;var isZeroOneLine=true;for(i=0;i<line.length;i++)
|
||||
{if(line.charAt(i)!='0'&&line.charAt(i)!='1')
|
||||
{isZeroOneLine=false;break;}}
|
||||
if(!isZeroOneLine)
|
||||
{if(separator!=",")
|
||||
{line=line.replace(/,/g,".");}
|
||||
for(i=0;i<line.length;i++)
|
||||
{if(("0123456789.-e").indexOf(line.charAt(i))<0)
|
||||
{if(i>0)
|
||||
{res.push(line.substr(0,i));}
|
||||
if(i==0)
|
||||
{i=1;}
|
||||
line=line.substr(i,line.length-i);i=-1;}}
|
||||
if(line.length>0)
|
||||
{res.push(line);}}
|
||||
else
|
||||
{for(i=0;i<line.length;i++)
|
||||
{res.push(line.charAt(i));}}
|
||||
console.log(res);return res;}
|
||||
Graph.prototype.SaveToXML=function(additionalData)
|
||||
{var mainHeader="<?xml version=\"1.0\" encoding=\"UTF-8\"?><graphml>";var header="<graph id=\"Graph\" uidGraph=\""+this.uidGraph+"\""+" uidEdge=\""+this.uidEdge+"\">";var xmlBody="";for(var i=0;i<this.vertices.length;i++)
|
||||
{xmlBody=xmlBody+this.vertices[i].SaveToXML();}
|
||||
xmlBody=xmlBody+"";for(var i=0;i<this.edges.length;i++)
|
||||
{xmlBody=xmlBody+this.edges[i].SaveToXML();}
|
||||
xmlBody=xmlBody+"";additionalField="";if(additionalData.length>0)
|
||||
{additionalField="<additional data=\""+additionalData+"\"/>"}
|
||||
return mainHeader+header+xmlBody+"</graph>"+additionalField+"</graphml>";}
|
||||
Graph.prototype.LoadFromXML=function(xmlText,additionalData)
|
||||
{xmlDoc=$.parseXML(xmlText);var $xml=$(xmlDoc);$graphs=$xml.find("graph");var loadedGraphId=0;var loadedEdgeId=0;$graphs.each(function(){loadedGraphId=parseInt($(this).attr('uidGraph'));loadedEdgeId=parseInt($(this).attr('uidEdge'));});if(isNaN(loadedEdgeId))
|
||||
{loadedEdgeId=this.edgesOffset;}else if(loadedEdgeId<this.edgesOffset)
|
||||
{loadedEdgeId=this.edgesOffset;}
|
||||
this.uidGraph=loadedGraphId;this.uidEdge=loadedEdgeId;$nodes=$xml.find("node");var vertices=[];$nodes.each(function(){var vertex=new BaseVertex();vertex.LoadFromXML($(this));vertices.push(vertex);});this.vertices=vertices;$edges=$xml.find("edge");var edges=[];var graph=this;$edges.each(function(){var edge=new BaseEdge();edge.LoadFromXML($(this),graph);if(edge.id<graph.uidEdge){edge.id=graph.uidEdge;graph.uidEdge++;}
|
||||
edges.push(edge);});this.edges=edges;$additional=$xml.find("additional");if($additional.length!=0&&additionalData!=null)
|
||||
{additionalData["data"]=$additional.attr('data');}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.hasDirectEdge=function()
|
||||
{var res=false;for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.hasUndirectEdge=function()
|
||||
{var res=false;for(var i=0;i<this.edges.length;i++)
|
||||
{if(!this.edges[i].isDirect)
|
||||
{res=true;break;}}
|
||||
return res;}
|
||||
Graph.prototype.hasEdges=function()
|
||||
{return this.edges.length>0;}
|
||||
Graph.prototype.clampPositions=function(viewportSize)
|
||||
{var diameter=(new VertexModel()).diameter;for(i=0;i<this.vertices.length;i++)
|
||||
{this.vertices[i].position.x=Math.min(Math.max(this.vertices[i].position.x,diameter),viewportSize.x-diameter);this.vertices[i].position.y=Math.min(Math.max(this.vertices[i].position.y,diameter),viewportSize.y-diameter);}}
|
||||
Graph.prototype.getGraphBBox=function(viewportSize)
|
||||
{var pointMin=new Point(1e5,1e5);var pointMax=new Point(-1e5,-1e5);var diameter=(new VertexModel()).diameter;for(i=0;i<this.vertices.length;i++)
|
||||
{var vertex=this.vertices[i];var factor=vertex.diameterFactor();var deltaVector=new Point(factor.x*diameter,factor.y*diameter);pointMin=pointMin.min(vertex.position.subtract(deltaVector));pointMax=pointMax.max(vertex.position.add(deltaVector));}
|
||||
var max_curve_length=32;for(i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if(edge.model.type==EdgeModels.curve)
|
||||
{var max_curve=edge.vertex2.position.subtract(edge.vertex1.position).length()/max_curve_length;for(j=0;j<max_curve;j++)
|
||||
{var point=edge.model.GetCurvePoint(edge.vertex1.position,edge.vertex2.position,j/max_curve);var deltaVector=new Point(max_curve_length,max_curve_length);pointMin=pointMin.min(point.subtract(deltaVector));pointMax=pointMax.max(point.add(deltaVector));}}}
|
||||
return new Rect(pointMin,pointMax);}
|
||||
Graph.prototype.hasPair=function(edge)
|
||||
{return this.FindPairFor(edge)!=null;}
|
||||
Graph.prototype.FindPairFor=function(edge)
|
||||
{var res=this.getNeighborEdges(edge);return res.length==1?res[0]:null;}
|
||||
Graph.prototype.getNeighborEdges=function(edge)
|
||||
{var res=[];for(var i=0;i<this.edges.length;i++)
|
||||
{var curEdge=this.edges[i];if(curEdge==edge)
|
||||
continue;if((curEdge.vertex1.id==edge.vertex1.id&&curEdge.vertex2.id==edge.vertex2.id)||(curEdge.vertex1.id==edge.vertex2.id&&curEdge.vertex2.id==edge.vertex1.id))
|
||||
{res.push(curEdge);}}
|
||||
return res;}
|
||||
Graph.prototype.checkMutiGraph=function()
|
||||
{var res=false;var start={};for(var i=0;i<this.edges.length;i++)
|
||||
{var edge=this.edges[i];if(start.hasOwnProperty(edge.vertex1.id)&&start[edge.vertex1.id]==edge.vertex2.id)
|
||||
{res=true;break;}
|
||||
start[edge.vertex1.id]=edge.vertex2.id;if(!edge.isDirect)
|
||||
{if(start.hasOwnProperty(edge.vertex2.id)&&start[edge.vertex2.id]==edge.vertex1.id)
|
||||
{res=true;break;}
|
||||
start[edge.vertex2.id]=edge.vertex1.id;}}
|
||||
return res;}
|
||||
Graph.prototype.isMulti=function()
|
||||
{return this.isMultiGraph;}
|
||||
Graph.prototype.isNeedReposition=function()
|
||||
{var res=false;for(var i=0;i<this.vertices.length;i++)
|
||||
{res=res||this.vertices[i].IsUndefinedPosition();}
|
||||
return res;}
|
||||
Graph.prototype.FixEdgeCurve=function(edgeIndex)
|
||||
{var edgeObject=this.edges[edgeIndex];var hasPair=this.hasPair(edgeObject);var neighborEdges=this.getNeighborEdges(edgeObject);if(hasPair)
|
||||
{if(edgeObject.model.default)
|
||||
edgeObject.model.type=EdgeModels.curve;var pairEdge=this.FindPairFor(edgeObject);if(pairEdge.model.default)
|
||||
{pairEdge.model.type=EdgeModels.curve;if(pairEdge.vertex1==edgeObject.vertex1&&pairEdge.vertex2==edgeObject.vertex2)
|
||||
pairEdge.model.curveValue=-pairEdge.model.curveValue;}}
|
||||
else if(neighborEdges.length>=2)
|
||||
{var curve=this.GetAvailableCurveValue(neighborEdges,edgeObject);if(edgeObject.model.default)
|
||||
{edgeObject.model.type=EdgeModels.curve;edgeObject.model.curveValue=curve;}}}
|
||||
Graph.prototype.GetAvailableCurveValue=function(neighborEdges,originalEdge)
|
||||
{var values=[];for(var i=0;i<neighborEdges.length;i++)
|
||||
{var edge=neighborEdges[i];var sameDirection=(originalEdge.vertex1.id==edge.vertex1.id);if(edge.model.type==EdgeModels.curve)
|
||||
{values[(sameDirection?edge.model.curveValue:-edge.model.curveValue)]=true;}}
|
||||
var changeValue=DefaultHandler.prototype.curveValue;var defaultValue=0.0;var maxSearch=10;for(var i=1;i<maxSearch;i++)
|
||||
{value=i*changeValue;if(!values.hasOwnProperty(value))
|
||||
return value;value=-i*changeValue;if(!values.hasOwnProperty(value))
|
||||
return value;}
|
||||
return defaultValue;}
|
||||
Graph.prototype.reverseAllEdges=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{let v1=this.edges[i].vertex1;this.edges[i].vertex1=this.edges[i].vertex2;this.edges[i].vertex2=v1;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.makeAllEdgesDirected=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(!this.edges[i].isDirect)
|
||||
{this.edges[i].isDirect=true;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
Graph.prototype.makeAllEdgesUndirected=function()
|
||||
{for(var i=0;i<this.edges.length;i++)
|
||||
{if(this.edges[i].isDirect)
|
||||
{this.edges[i].isDirect=false;}}
|
||||
this.isMultiGraph=this.checkMutiGraph();}
|
||||
window.onload=function()
|
||||
{if(document.getElementById('CreateByAdjacencyMatrix'))
|
||||
{document.getElementById('CreateByAdjacencyMatrix').onclick=function()
|
||||
{window.location="./?matrix="+$("#AdjacencyMatrixFieldPage").val();}}}
|
||||
var g_MatrixSize=3;var g_ctrlPressed=false;function PackMatrix()
|
||||
{var matrix="";for(i=0;i<g_MatrixSize;i++)
|
||||
{for(j=0;j<g_MatrixSize;j++)
|
||||
{var element=document.getElementsByName("field"+i+"_"+j)[0];matrix=matrix+(element.value.length>0?element.value:"0")+", ";}
|
||||
matrix=matrix+"\n";}
|
||||
return matrix;}
|
||||
function getCharCode(event)
|
||||
{if(event.which==null)
|
||||
{return event.keyCode;}
|
||||
if(event.which!=0)
|
||||
{return event.which;}
|
||||
return null;}
|
||||
function getChar(event)
|
||||
{var k=getCharCode(event)
|
||||
return String.fromCharCode(k);}
|
||||
function CopyMatrixToTextInput(event)
|
||||
{document.getElementById("AdjacencyMatrixFieldPage").value=PackMatrix();if(event)
|
||||
{var key=getChar(event);var code=getCharCode(event);console.log(key+" code="+code);if(g_ctrlPressed)
|
||||
{var moveFocus=function(offsetX,offsetY)
|
||||
{var focused_element=document.activeElement;if(focused_element&&focused_element.name.includes("field"))
|
||||
{var name=focused_element.name;var coords=name.replace('field','').split("_");if(coords.length==2)
|
||||
{var focusName="field"+(parseInt(coords[0])+offsetY)+"_"+(parseInt(coords[1])+offsetX)
|
||||
var element=document.getElementsByName(focusName)[0];if(element)
|
||||
{element.focus();}}}}
|
||||
switch(code)
|
||||
{case 38:{moveFocus(0,-1);break;}
|
||||
case 40:{moveFocus(0,1);break;}
|
||||
case 37:{moveFocus(-1,0);break;}
|
||||
case 39:{moveFocus(1,0);break;}}}}}
|
||||
function _ShowTextInput()
|
||||
{$("#AdjacencyMatrixFieldPage").show();$("#MatrixForm").hide();$("#TextDescription").show();$("#MatrixDescription").hide();$("#idSeparatorList").show();}
|
||||
function _ShowMatrixInput()
|
||||
{$("#MatrixForm").show();$("#AdjacencyMatrixFieldPage").hide();$("#TextDescription").hide();$("#MatrixDescription").show();$("#idSeparatorList").hide();}
|
||||
function ShowTextInput()
|
||||
{_ShowTextInput();document.getElementById("showMatrix").className="btn btn-default";document.getElementById("showText").className="btn btn-default active";}
|
||||
function ShowMatrixInput()
|
||||
{_ShowMatrixInput();document.getElementById("showMatrix").className="btn btn-default active";document.getElementById("showText").className="btn btn-default";}
|
||||
function CopyMatrixToMatrixInput()
|
||||
{var graph=new Graph();var colsObj={};var rowsObj={};if(graph.TestAdjacencyMatrix($("#AdjacencyMatrixFieldPage").val(),rowsObj,colsObj))
|
||||
{var rows=rowsObj.rows;var cols=colsObj.cols;for(var i=g_MatrixSize;i<rows.length;i++)
|
||||
{IncSize();}
|
||||
for(var i=0;i<rows.length;i++)
|
||||
{for(var j=0;j<rows.length;j++)
|
||||
{var element=document.getElementsByName("field"+i+"_"+j)[0];element.value=cols[i][j];}}}
|
||||
else
|
||||
{ShowTextInput();}}
|
||||
function CreateInputElement(col,row)
|
||||
{var input=document.createElement("input");input.type="text";input.size=3;input.name="field"+col+"_"+row;input.value=0;input.onkeyup=function(event){CopyMatrixToTextInput(event);};return input;}
|
||||
function InsertBeforeElement(element,beforeName,space)
|
||||
{var parent=document.getElementsByName(beforeName)[0].parentNode;var beforeElement=document.getElementsByName(beforeName)[0];parent.insertBefore(element,beforeElement);if(space)
|
||||
{parent.insertBefore(document.createTextNode('\u00A0'),beforeElement);}}
|
||||
function IncSize()
|
||||
{for(var i=0;i<g_MatrixSize;i++)
|
||||
{var input=CreateInputElement(g_MatrixSize,i);InsertBeforeElement(input,"matrixEnd",true);}
|
||||
var br=document.createElement("br");br.setAttribute("name","row"+g_MatrixSize);InsertBeforeElement(br,"matrixEnd",false);for(var i=0;i<g_MatrixSize+1;i++)
|
||||
{var input=CreateInputElement(i,g_MatrixSize);InsertBeforeElement(input,"row"+i,g_MatrixSize);}
|
||||
g_MatrixSize++;CopyMatrixToTextInput();}
|
||||
function checkFormat()
|
||||
{var graph=new Graph();var separator=$("#spaceSep").is(':checked')?" ":",";if(!graph.TestAdjacencyMatrix($("#AdjacencyMatrixFieldPage").val(),[],[],separator))
|
||||
{$("#BadFormatMessage").show();}
|
||||
else
|
||||
{$("#BadFormatMessage").hide();}}
|
||||
window.onload=function()
|
||||
{if(document.getElementById('CreateByAdjacencyMatrix'))
|
||||
{document.getElementById('CreateByAdjacencyMatrix').onclick=function()
|
||||
{$("#matrixForm").submit();}}
|
||||
$("#AdjacencyMatrixFieldPage").on('keyup change',function(eventObject)
|
||||
{checkFormat();});$("#BadFormatMessage").hide();$("#AdjacencyMatrixFieldPage").hide();$("#showMatrix").on('click',function(eventObject)
|
||||
{_ShowMatrixInput();});$("#showText").on('click',function(eventObject)
|
||||
{_ShowTextInput();});$('input:radio[name="separator"]').change(function(){checkFormat()});CopyMatrixToMatrixInput();$(document).keydown(function(event){if(event.which=="17"||event.which=="91")
|
||||
g_ctrlPressed=true;});$(document).keyup(function(event){if(event.which=="17"||event.which=="91")
|
||||
g_ctrlPressed=false;});}
|
||||
moduleLoader.endCacheLoading();
|
0
script/createByMatrixMain.js → script/pages/create_graph_by_matrix/model/createByMatrixMain.js
Executable file → Normal file
0
script/createByMatrixMain.js → script/pages/create_graph_by_matrix/model/createByMatrixMain.js
Executable file → Normal file
272
script/pages/create_graph_by_matrix/model/main.js
Normal file
272
script/pages/create_graph_by_matrix/model/main.js
Normal file
@ -0,0 +1,272 @@
|
||||
// Current matrix size
|
||||
var g_MatrixSize = 3;
|
||||
var g_ctrlPressed = false;
|
||||
|
||||
function PackMatrix()
|
||||
{
|
||||
var matrix = "";
|
||||
|
||||
for (i = 0; i < g_MatrixSize; i++)
|
||||
{
|
||||
for (j = 0; j < g_MatrixSize; j++)
|
||||
{
|
||||
var element = document.getElementsByName("field" + i + "_" + j)[0];
|
||||
matrix = matrix + (element.value.length > 0 ? element.value : "0") + ", ";
|
||||
}
|
||||
matrix = matrix + "\n";
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
function getCharCode(event)
|
||||
{
|
||||
if (event.which == null)
|
||||
{ // IE
|
||||
return event.keyCode;
|
||||
}
|
||||
|
||||
if (event.which != 0)
|
||||
{ // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> IE
|
||||
return event.which; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
return null; // <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
function getChar(event)
|
||||
{
|
||||
var k = getCharCode(event)
|
||||
return String.fromCharCode(k); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
function CopyMatrixToTextInput(event)
|
||||
{
|
||||
document.getElementById("AdjacencyMatrixFieldPage").value = PackMatrix();
|
||||
|
||||
// Move between cells.
|
||||
if (event)
|
||||
{
|
||||
var key = getChar(event);
|
||||
var code = getCharCode(event);
|
||||
console.log(key + " code=" + code);
|
||||
if (g_ctrlPressed)
|
||||
{
|
||||
var moveFocus = function(offsetX, offsetY)
|
||||
{
|
||||
var focused_element = document.activeElement;
|
||||
|
||||
if (focused_element && focused_element.name.includes("field"))
|
||||
{
|
||||
var name = focused_element.name;
|
||||
var coords = name.replace('field','').split("_");
|
||||
if (coords.length == 2)
|
||||
{
|
||||
var focusName = "field" + (parseInt(coords[0]) + offsetY) + "_" + (parseInt(coords[1]) + offsetX)
|
||||
var element = document.getElementsByName(focusName)[0];
|
||||
if (element)
|
||||
{
|
||||
element.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case 38: // Up
|
||||
{
|
||||
moveFocus(0, -1);
|
||||
break;
|
||||
}
|
||||
case 40: // Down
|
||||
{
|
||||
moveFocus(0, 1);
|
||||
break;
|
||||
}
|
||||
case 37: // Left
|
||||
{
|
||||
moveFocus(-1, 0);
|
||||
break;
|
||||
}
|
||||
case 39: // Right
|
||||
{
|
||||
moveFocus(1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _ShowTextInput()
|
||||
{
|
||||
$( "#AdjacencyMatrixFieldPage" ).show();
|
||||
$( "#MatrixForm" ).hide();
|
||||
$( "#TextDescription").show();
|
||||
$( "#MatrixDescription").hide();
|
||||
$( "#idSeparatorList").show();
|
||||
}
|
||||
|
||||
function _ShowMatrixInput()
|
||||
{
|
||||
$( "#MatrixForm" ).show();
|
||||
$( "#AdjacencyMatrixFieldPage" ).hide();
|
||||
$( "#TextDescription").hide();
|
||||
$( "#MatrixDescription").show();
|
||||
$( "#idSeparatorList").hide();
|
||||
}
|
||||
|
||||
function ShowTextInput()
|
||||
{
|
||||
_ShowTextInput();
|
||||
document.getElementById("showMatrix").className = "btn btn-default";
|
||||
document.getElementById("showText").className = "btn btn-default active";
|
||||
}
|
||||
|
||||
function ShowMatrixInput()
|
||||
{
|
||||
_ShowMatrixInput();
|
||||
document.getElementById("showMatrix").className = "btn btn-default active";
|
||||
document.getElementById("showText").className = "btn btn-default";
|
||||
}
|
||||
|
||||
function CopyMatrixToMatrixInput()
|
||||
{
|
||||
var graph = new Graph();
|
||||
|
||||
var colsObj = {};
|
||||
var rowsObj = {};
|
||||
|
||||
if (graph.TestAdjacencyMatrix($( "#AdjacencyMatrixFieldPage" ).val(), rowsObj, colsObj))
|
||||
{
|
||||
var rows = rowsObj.rows;
|
||||
var cols = colsObj.cols;
|
||||
|
||||
for (var i = g_MatrixSize; i < rows.length; i++)
|
||||
{
|
||||
IncSize();
|
||||
}
|
||||
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
{
|
||||
for (var j = 0; j < rows.length; j++)
|
||||
{
|
||||
var element = document.getElementsByName("field" + i + "_"+ j)[0];
|
||||
element.value = cols[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowTextInput();
|
||||
}
|
||||
}
|
||||
|
||||
function CreateInputElement(col, row)
|
||||
{
|
||||
var input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.size = 3;
|
||||
input.name = "field" + col + "_" + row;
|
||||
input.value = 0;
|
||||
input.onkeyup = function(event) {CopyMatrixToTextInput(event);};
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
function InsertBeforeElement(element, beforeName, space)
|
||||
{
|
||||
var parent = document.getElementsByName(beforeName)[0].parentNode;
|
||||
var beforeElement = document.getElementsByName(beforeName)[0];
|
||||
parent.insertBefore(element, beforeElement);
|
||||
|
||||
if (space)
|
||||
{
|
||||
// Insert space
|
||||
parent.insertBefore(document.createTextNode( '\u00A0' ), beforeElement);
|
||||
}
|
||||
}
|
||||
|
||||
function IncSize()
|
||||
{
|
||||
// End one more line:
|
||||
for (var i = 0; i < g_MatrixSize; i ++)
|
||||
{
|
||||
var input = CreateInputElement(g_MatrixSize, i);
|
||||
InsertBeforeElement(input, "matrixEnd", true);
|
||||
}
|
||||
var br = document.createElement("br");
|
||||
br.setAttribute("name", "row" + g_MatrixSize);
|
||||
InsertBeforeElement(br, "matrixEnd", false);
|
||||
|
||||
for (var i = 0; i < g_MatrixSize + 1; i ++)
|
||||
{
|
||||
var input = CreateInputElement(i, g_MatrixSize);
|
||||
InsertBeforeElement(input, "row" + i, g_MatrixSize);
|
||||
}
|
||||
g_MatrixSize++;
|
||||
CopyMatrixToTextInput();
|
||||
}
|
||||
|
||||
function checkFormat()
|
||||
{
|
||||
var graph = new Graph();
|
||||
var separator = $("#spaceSep").is(':checked') ? " " : ",";
|
||||
|
||||
if (!graph.TestAdjacencyMatrix($( "#AdjacencyMatrixFieldPage" ).val(), [], [], separator))
|
||||
{
|
||||
$( "#BadFormatMessage" ).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$( "#BadFormatMessage" ).hide();
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function ()
|
||||
{
|
||||
|
||||
if (document.getElementById('CreateByAdjacencyMatrix'))
|
||||
{
|
||||
document.getElementById('CreateByAdjacencyMatrix').onclick = function ()
|
||||
{
|
||||
$("#matrixForm").submit();
|
||||
//window.location = "./?matrix=" + $( "#AdjacencyMatrixFieldPage" ).val().replace(/\n/g,'%0A');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$( "#AdjacencyMatrixFieldPage" ).on('keyup change', function (eventObject)
|
||||
{
|
||||
checkFormat();
|
||||
});
|
||||
|
||||
$( "#BadFormatMessage" ).hide();
|
||||
$( "#AdjacencyMatrixFieldPage" ).hide();
|
||||
|
||||
$( "#showMatrix" ).on('click', function (eventObject)
|
||||
{
|
||||
_ShowMatrixInput();
|
||||
});
|
||||
|
||||
$( "#showText" ).on('click', function (eventObject)
|
||||
{
|
||||
_ShowTextInput();
|
||||
});
|
||||
|
||||
$('input:radio[name="separator"]').change( function(){
|
||||
checkFormat()
|
||||
});
|
||||
|
||||
CopyMatrixToMatrixInput();
|
||||
|
||||
$(document).keydown(function(event) {
|
||||
if (event.which == "17" || event.which == "91")
|
||||
g_ctrlPressed = true;
|
||||
});
|
||||
|
||||
$(document).keyup(function(event) {
|
||||
if (event.which == "17" || event.which == "91")
|
||||
g_ctrlPressed = false;
|
||||
});
|
||||
}
|
55
script/pages/editor/api/index.js
Normal file
55
script/pages/editor/api/index.js
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
// Global version needs to force reload scripts from server.
|
||||
globalVersion = 75;
|
||||
|
||||
{
|
||||
let asyncFilesLoad = null;
|
||||
function onloadEditor() {
|
||||
console.log("onload() call");
|
||||
asyncFilesLoad();
|
||||
preLoadPage();
|
||||
postLoadPage();
|
||||
}
|
||||
|
||||
let modulDir = "pages/editor/";
|
||||
|
||||
doInclude ([
|
||||
include ("shared/utils.js"),
|
||||
|
||||
include ("entities/graph/api/index.js"),
|
||||
include ("features/draw_graph/api/index.js"),
|
||||
include ("features/algorithms/api/index.js"),
|
||||
|
||||
include ("features/base_handler/index.js"),
|
||||
include ("features/default_handler/index.js"),
|
||||
include ("features/add_vertices_handler/index.js"),
|
||||
include ("features/connect_vertices_handler/index.js"),
|
||||
include ("features/delete_objects_handler/index.js"),
|
||||
include ("features/algorithm_handler/index.js"),
|
||||
|
||||
include ("features/serialization/api/index.js"),
|
||||
|
||||
include ("features/enum_vertices/EnumVertices.js"),
|
||||
|
||||
include ("model/texts.js", modulDir),
|
||||
include ("model/Application.js", modulDir),
|
||||
include ("ui/main.js", modulDir)],
|
||||
onloadEditor);
|
||||
|
||||
|
||||
asyncFilesLoad = function () {
|
||||
doIncludeAsync ([
|
||||
include ("shared/canvas2svg.js"),
|
||||
include ("features/group_rename_handler/index.js"),
|
||||
include ("features/saved_graph_handler/index.js"),
|
||||
include ("features/saved_graph_image_handler/index.js"),
|
||||
include ("features/show_adjacency_matrix/index.js"),
|
||||
include ("features/show_distance_matrix/index.js"),
|
||||
include ("features/show_incidence_matrix/index.js"),
|
||||
include ("features/setup_background_style/index.js"),
|
||||
include ("features/setup_edge_style/index.js"),
|
||||
include ("features/setup_vertex_style/index.js"),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
2031
script/pages/editor/api/index.js.cache
Normal file
2031
script/pages/editor/api/index.js.cache
Normal file
File diff suppressed because one or more lines are too long
@ -421,9 +421,3 @@ function loadTexts()
|
||||
g_wrongImageFormatPNGAndJPEG = document.getElementById("wrongImageFormatPNGAndJPEG").innerHTML;
|
||||
g_wrongImageSizeP1 = document.getElementById("wrongImageSizeP1").innerHTML;
|
||||
}
|
||||
|
||||
function formatString(string, params) {
|
||||
return string.replace(/{(\d+)}/g, (match, index) => {
|
||||
return typeof params[index] !== 'undefined' ? params[index] : match;
|
||||
});
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
|
||||
var SiteDir = "";
|
||||
var DisableEmscripten = false;
|
||||
var algorithmsVersion = 2;
|
||||
|
||||
@ -33,7 +32,7 @@ var g_ctrlPressed = false;
|
||||
function restButtons (me)
|
||||
{
|
||||
var needSetDefault = false;
|
||||
for (var i = 0; i < buttonsList.length; i ++)
|
||||
for (let i = 0; i < buttonsList.length; i ++)
|
||||
{
|
||||
if (buttonsList[i] != me)
|
||||
{
|
||||
@ -49,7 +48,7 @@ function restButtons (me)
|
||||
}
|
||||
if (needSetDefault)
|
||||
{
|
||||
document.getElementById(buttonsList[i]).className = "btn btn-primary btn-sm";
|
||||
document.getElementById(me).className = "btn btn-primary btn-sm";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -651,31 +650,7 @@ function postLoadPage()
|
||||
}
|
||||
|
||||
// Get algorithms list and load it.
|
||||
$.get( "/" + SiteDir + "cgi-bin/getPluginsList.php",
|
||||
function( data )
|
||||
{
|
||||
var scriptList = JSON.parse(data);
|
||||
|
||||
var loadOneScript = function()
|
||||
{
|
||||
if (scriptList.length == 0)
|
||||
{
|
||||
createAlgorithmMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
var script = document.createElement('script');
|
||||
script.src = "/" + SiteDir + "script/" + scriptList[0] + "?v=" + algorithmsVersion;
|
||||
scriptList.shift();
|
||||
script.onload = loadOneScript;
|
||||
script.onerror = loadOneScript;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
}
|
||||
|
||||
loadOneScript();
|
||||
|
||||
});
|
||||
loadAsyncAlgorithms(createAlgorithmMenu);
|
||||
|
||||
var devTools = document.getElementById('developerTools');
|
||||
devTools.style.left = 0;
|
||||
@ -743,16 +718,16 @@ $(document).ready(function ()
|
||||
// Try load emscripten implementation
|
||||
var isMobile = navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i);
|
||||
if (!isMobile && !DisableEmscripten) {
|
||||
const jsScript = document.createElement('script');
|
||||
jsScript.src = '/script/Graphoffline.Emscripten.js?v=1';
|
||||
document.body.appendChild(jsScript);
|
||||
jsScript.addEventListener('load', () => {
|
||||
let fullPathToGraphffoline = "features/graphoffline/Graphoffline.Emscripten.js";
|
||||
doIncludeAsync ([
|
||||
include (fullPathToGraphffoline),
|
||||
], () => {
|
||||
Module['onRuntimeInitialized'] = onRuntimeInitialized;
|
||||
var process = Module.cwrap('ProcessAlgorithm', 'string', ['string']);
|
||||
function onRuntimeInitialized() {
|
||||
application.setEmscripten(process);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
/*
|
||||
$(document).ready(function(){
|
2
script/shared/config.js
Normal file
2
script/shared/config.js
Normal file
@ -0,0 +1,2 @@
|
||||
let SiteDir = ""; // Used for load from sub directory
|
||||
let UseCache = true;
|
199
script/shared/loader.js
Normal file
199
script/shared/loader.js
Normal file
@ -0,0 +1,199 @@
|
||||
var include = function(filename, localDir) {
|
||||
return {filename: filename, localDir: localDir};
|
||||
};
|
||||
|
||||
class ModuleLoader {
|
||||
constructor(name) {
|
||||
this.loadingStack = [];
|
||||
this.startedLoading = new Set();
|
||||
this.loaded = new Set();
|
||||
this.isRunningSync = false;
|
||||
this.syncLoaded = [];
|
||||
this.cacheLoading = false;
|
||||
this.callsAfterCacheResolve = [];
|
||||
}
|
||||
|
||||
getFullname = function (filename, localDir)
|
||||
{
|
||||
let versionParam = "";
|
||||
if (typeof globalVersion !== 'undefined') {
|
||||
versionParam = "?v=" + globalVersion;
|
||||
}
|
||||
let localDirParam = "";
|
||||
if (typeof localDir !== 'undefined') {
|
||||
localDirParam = localDir;
|
||||
}
|
||||
return "/" + SiteDir + "script/" + localDirParam + filename + "?v=" + globalVersion;
|
||||
}
|
||||
|
||||
isAllLoaded = function (includes)
|
||||
{
|
||||
self = this;
|
||||
return includes.every((inc) => {
|
||||
return self.loaded.has(inc);
|
||||
});
|
||||
}
|
||||
|
||||
load = function (fullFilename, checkQueue, sync) {
|
||||
let self = this;
|
||||
|
||||
let loadError = function()
|
||||
{
|
||||
console.error("Cannot load " + fullFilename);
|
||||
checkQueue();
|
||||
}
|
||||
let loadSuccess = function()
|
||||
{
|
||||
self.loaded.add(fullFilename);
|
||||
console.log(self.loaded.size + ". " + fullFilename);
|
||||
checkQueue();
|
||||
}
|
||||
|
||||
if (this.loaded.has(fullFilename)) {
|
||||
this.isRunning = true;
|
||||
checkQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = fullFilename;
|
||||
script.onload = loadSuccess;
|
||||
script.onerror = loadError;
|
||||
document.head.appendChild(script);
|
||||
this.isRunning = true;
|
||||
if (sync) {
|
||||
this.syncLoaded.push(fullFilename);
|
||||
}
|
||||
}
|
||||
|
||||
loadFromQueue = function (checkQueue) {
|
||||
if (this.loadingStack.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let fullFilename = this.loadingStack.pop();
|
||||
this.load(fullFilename, checkQueue, true);
|
||||
this.isRunning = true;
|
||||
}
|
||||
|
||||
// Load modules one by one in sync mode.
|
||||
// Call fullLoadedCallback when all modules loaded.
|
||||
doInclude = function (includes, fullLoadedCallback) {
|
||||
let self = this;
|
||||
|
||||
if (this.cacheLoading) {
|
||||
this.callsAfterCacheResolve.push(
|
||||
function() {
|
||||
self.doInclude(includes, fullLoadedCallback);
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let checkQueue = function () {
|
||||
if (self.loadingStack.length != 0) {
|
||||
self.loadFromQueue(checkQueue);
|
||||
return;
|
||||
}
|
||||
|
||||
self.isRunning = false;
|
||||
if (typeof fullLoadedCallback === 'undefined' || fullLoadedCallback === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
fullLoadedCallback();
|
||||
}
|
||||
|
||||
let pushToQueue = function (fullFilename) {
|
||||
self.loadingStack.push(fullFilename)
|
||||
self.startedLoading.add(fullFilename);
|
||||
}
|
||||
|
||||
let reversedIncludes = includes.reverse();
|
||||
|
||||
reversedIncludes.forEach((inc) => {
|
||||
let fullFilename = self.getFullname(inc.filename, inc.localDir);
|
||||
if (self.startedLoading.has(fullFilename)) {
|
||||
return;
|
||||
}
|
||||
pushToQueue(fullFilename)
|
||||
});
|
||||
|
||||
if (!self.isRunning) {
|
||||
checkQueue();
|
||||
}
|
||||
}
|
||||
|
||||
// Load modules async start load all modules.
|
||||
// Call fullLoadedCallback when all includes loaded.
|
||||
doIncludeAsync = function (includes, fullLoadedCallback) {
|
||||
let self = this;
|
||||
if (this.cacheLoading) {
|
||||
this.callsAfterCacheResolve.push(
|
||||
function() {
|
||||
self.doIncludeAsync(includes, fullLoadedCallback);
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let includesFull = [];
|
||||
|
||||
let checkLoading = function () {
|
||||
self.isRunning = false;
|
||||
if (typeof fullLoadedCallback === 'undefined' || fullLoadedCallback === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.isAllLoaded(includesFull)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fullLoadedCallback();
|
||||
}
|
||||
|
||||
let pushToQueue = function (fullFilename) {
|
||||
self.load(fullFilename, checkLoading, false);
|
||||
self.startedLoading.add(fullFilename);
|
||||
}
|
||||
|
||||
let reversedIncludes = includes.reverse();
|
||||
|
||||
reversedIncludes.forEach((inc) => {
|
||||
let fullFilename = self.getFullname(inc.filename, inc.localDir);
|
||||
includesFull.push(fullFilename);
|
||||
if (self.startedLoading.has(fullFilename)) {
|
||||
return;
|
||||
}
|
||||
pushToQueue(fullFilename)
|
||||
});
|
||||
|
||||
checkLoading();
|
||||
}
|
||||
|
||||
beginCacheLoading = function (cachedFiles) {
|
||||
let self = this;
|
||||
cachedFiles.forEach((file) => {
|
||||
self.startedLoading.add(file);
|
||||
self.loaded.add(file);
|
||||
});
|
||||
this.cacheLoading = true;
|
||||
}
|
||||
|
||||
endCacheLoading = function () {
|
||||
this.cacheLoading = false;
|
||||
this.callsAfterCacheResolve.forEach((func) => {
|
||||
func();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let moduleLoader = new ModuleLoader();
|
||||
|
||||
function doInclude(includes, callback) {
|
||||
moduleLoader.doInclude(includes, callback);
|
||||
}
|
||||
|
||||
function doIncludeAsync(includes, callback) {
|
||||
moduleLoader.doIncludeAsync(includes, callback);
|
||||
}
|
0
script/point.js → script/shared/point.js
Executable file → Normal file
0
script/point.js → script/shared/point.js
Executable file → Normal file
@ -42,3 +42,9 @@ function FullArrayCopy(arr)
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function formatString(string, params) {
|
||||
return string.replace(/{(\d+)}/g, (match, index) => {
|
||||
return typeof params[index] !== 'undefined' ? params[index] : match;
|
||||
});
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="<?= Root('i/css/create_graph_by_pair.css')?>" />
|
||||
<script src="<?= Root('script/Graph.js')?>"></script>
|
||||
<script src="<?= RootCacheJS("script/shared/config.js")?>" ></script>
|
||||
<script src="<?= RootCacheJS("script/shared/loader.js")?>" ></script>
|
||||
|
||||
<script src="<?= RootCacheJS('script/pages/create_graph_by_edge_list/api/index.js')?>"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
|
||||
function checkFormat()
|
||||
{
|
||||
var graph = new Graph();
|
||||
|
@ -1,6 +1,8 @@
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="<?= Root('i/css/create_graph_by_incidence_matrix.css')?>" />
|
||||
<script src="<?= Root('script/Graph.js')?>"></script>
|
||||
<script src="<?= RootCacheJS("script/shared/config.js")?>" ></script>
|
||||
<script src="<?= RootCacheJS("script/shared/loader.js")?>" ></script>
|
||||
<script src="<?= RootCacheJS('script/pages/create_graph_by_incidence_matrix/api/index.js')?>"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
@ -304,11 +306,11 @@ window.onload = function ()
|
||||
|
||||
<form action="./" method="post" id="matrixForm">
|
||||
<textarea name="incidenceMatrix" id="IncidenceMatrixFieldPage" wrap="off" style="display: none;">
|
||||
<? if (!isset($_GET["incidenceMatrix"])): ?>
|
||||
<?php if (!isset($_GET["incidenceMatrix"])): ?>
|
||||
1, 0
|
||||
1, 1
|
||||
0, -1
|
||||
<? else: ?><?= $_GET["incidenceMatrix"] ?><? endif;?></textarea>
|
||||
<?php else: ?><?= $_GET["incidenceMatrix"] ?><?php endif;?></textarea>
|
||||
</form>
|
||||
<div id="MatrixForm">
|
||||
<form id="AdjacencyMatrixFieldInput" role="form">
|
||||
|
@ -1,287 +1,10 @@
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="<?= Root('i/css/create_graph_by_matrix.css')?>" />
|
||||
<script src="<?= Root('script/Graph.js')?>"></script>
|
||||
|
||||
<script src="<?= RootCacheJS("script/shared/config.js")?>" ></script>
|
||||
<script src="<?= RootCacheJS("script/shared/loader.js")?>" ></script>
|
||||
<script src="<?= RootCacheJS('script/pages/create_graph_by_matrix/api/index.js')?>"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
|
||||
// Current matrix size
|
||||
var g_MatrixSize = 3;
|
||||
var g_ctrlPressed = false;
|
||||
|
||||
function PackMatrix()
|
||||
{
|
||||
var matrix = "";
|
||||
|
||||
for (i = 0; i < g_MatrixSize; i++)
|
||||
{
|
||||
for (j = 0; j < g_MatrixSize; j++)
|
||||
{
|
||||
var element = document.getElementsByName("field" + i + "_" + j)[0];
|
||||
matrix = matrix + (element.value.length > 0 ? element.value : "0") + ", ";
|
||||
}
|
||||
matrix = matrix + "\n";
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
function getCharCode(event)
|
||||
{
|
||||
if (event.which == null)
|
||||
{ // IE
|
||||
return event.keyCode;
|
||||
}
|
||||
|
||||
if (event.which != 0)
|
||||
{ // все кроме IE
|
||||
return event.which; // остальные
|
||||
}
|
||||
|
||||
return null; // спец. символ
|
||||
}
|
||||
|
||||
function getChar(event)
|
||||
{
|
||||
var k = getCharCode(event)
|
||||
return String.fromCharCode(k); // остальные
|
||||
}
|
||||
|
||||
function CopyMatrixToTextInput(event)
|
||||
{
|
||||
document.getElementById("AdjacencyMatrixFieldPage").value = PackMatrix();
|
||||
|
||||
// Move between cells.
|
||||
if (event)
|
||||
{
|
||||
var key = getChar(event);
|
||||
var code = getCharCode(event);
|
||||
console.log(key + " code=" + code);
|
||||
if (g_ctrlPressed)
|
||||
{
|
||||
var moveFocus = function(offsetX, offsetY)
|
||||
{
|
||||
var focused_element = document.activeElement;
|
||||
|
||||
if (focused_element && focused_element.name.includes("field"))
|
||||
{
|
||||
var name = focused_element.name;
|
||||
var coords = name.replace('field','').split("_");
|
||||
if (coords.length == 2)
|
||||
{
|
||||
var focusName = "field" + (parseInt(coords[0]) + offsetY) + "_" + (parseInt(coords[1]) + offsetX)
|
||||
var element = document.getElementsByName(focusName)[0];
|
||||
if (element)
|
||||
{
|
||||
element.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case 38: // Up
|
||||
{
|
||||
moveFocus(0, -1);
|
||||
break;
|
||||
}
|
||||
case 40: // Down
|
||||
{
|
||||
moveFocus(0, 1);
|
||||
break;
|
||||
}
|
||||
case 37: // Left
|
||||
{
|
||||
moveFocus(-1, 0);
|
||||
break;
|
||||
}
|
||||
case 39: // Right
|
||||
{
|
||||
moveFocus(1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _ShowTextInput()
|
||||
{
|
||||
$( "#AdjacencyMatrixFieldPage" ).show();
|
||||
$( "#MatrixForm" ).hide();
|
||||
$( "#TextDescription").show();
|
||||
$( "#MatrixDescription").hide();
|
||||
$( "#idSeparatorList").show();
|
||||
}
|
||||
|
||||
function _ShowMatrixInput()
|
||||
{
|
||||
$( "#MatrixForm" ).show();
|
||||
$( "#AdjacencyMatrixFieldPage" ).hide();
|
||||
$( "#TextDescription").hide();
|
||||
$( "#MatrixDescription").show();
|
||||
$( "#idSeparatorList").hide();
|
||||
}
|
||||
|
||||
function ShowTextInput()
|
||||
{
|
||||
_ShowTextInput();
|
||||
document.getElementById("showMatrix").className = "btn btn-default";
|
||||
document.getElementById("showText").className = "btn btn-default active";
|
||||
}
|
||||
|
||||
function ShowMatrixInput()
|
||||
{
|
||||
_ShowMatrixInput();
|
||||
document.getElementById("showMatrix").className = "btn btn-default active";
|
||||
document.getElementById("showText").className = "btn btn-default";
|
||||
}
|
||||
|
||||
function CopyMatrixToMatrixInput()
|
||||
{
|
||||
var graph = new Graph();
|
||||
|
||||
var colsObj = {};
|
||||
var rowsObj = {};
|
||||
|
||||
if (graph.TestAdjacencyMatrix($( "#AdjacencyMatrixFieldPage" ).val(), rowsObj, colsObj))
|
||||
{
|
||||
var rows = rowsObj.rows;
|
||||
var cols = colsObj.cols;
|
||||
|
||||
for (var i = g_MatrixSize; i < rows.length; i++)
|
||||
{
|
||||
IncSize();
|
||||
}
|
||||
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
{
|
||||
for (var j = 0; j < rows.length; j++)
|
||||
{
|
||||
var element = document.getElementsByName("field" + i + "_"+ j)[0];
|
||||
element.value = cols[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowTextInput();
|
||||
}
|
||||
}
|
||||
|
||||
function CreateInputElement(col, row)
|
||||
{
|
||||
var input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.size = 3;
|
||||
input.name = "field" + col + "_" + row;
|
||||
input.value = 0;
|
||||
input.onkeyup = function(event) {CopyMatrixToTextInput(event);};
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
function InsertBeforeElement(element, beforeName, space)
|
||||
{
|
||||
var parent = document.getElementsByName(beforeName)[0].parentNode;
|
||||
var beforeElement = document.getElementsByName(beforeName)[0];
|
||||
parent.insertBefore(element, beforeElement);
|
||||
|
||||
if (space)
|
||||
{
|
||||
// Insert space
|
||||
parent.insertBefore(document.createTextNode( '\u00A0' ), beforeElement);
|
||||
}
|
||||
}
|
||||
|
||||
function IncSize()
|
||||
{
|
||||
// End one more line:
|
||||
for (var i = 0; i < g_MatrixSize; i ++)
|
||||
{
|
||||
var input = CreateInputElement(g_MatrixSize, i);
|
||||
InsertBeforeElement(input, "matrixEnd", true);
|
||||
}
|
||||
var br = document.createElement("br");
|
||||
br.setAttribute("name", "row" + g_MatrixSize);
|
||||
InsertBeforeElement(br, "matrixEnd", false);
|
||||
|
||||
for (var i = 0; i < g_MatrixSize + 1; i ++)
|
||||
{
|
||||
var input = CreateInputElement(i, g_MatrixSize);
|
||||
InsertBeforeElement(input, "row" + i, g_MatrixSize);
|
||||
}
|
||||
g_MatrixSize++;
|
||||
CopyMatrixToTextInput();
|
||||
}
|
||||
|
||||
function checkFormat()
|
||||
{
|
||||
var graph = new Graph();
|
||||
var separator = $("#spaceSep").is(':checked') ? " " : ",";
|
||||
|
||||
if (!graph.TestAdjacencyMatrix($( "#AdjacencyMatrixFieldPage" ).val(), [], [], separator))
|
||||
{
|
||||
$( "#BadFormatMessage" ).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$( "#BadFormatMessage" ).hide();
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function ()
|
||||
{
|
||||
|
||||
if (document.getElementById('CreateByAdjacencyMatrix'))
|
||||
{
|
||||
document.getElementById('CreateByAdjacencyMatrix').onclick = function ()
|
||||
{
|
||||
$("#matrixForm").submit();
|
||||
//window.location = "./?matrix=" + $( "#AdjacencyMatrixFieldPage" ).val().replace(/\n/g,'%0A');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$( "#AdjacencyMatrixFieldPage" ).on('keyup change', function (eventObject)
|
||||
{
|
||||
checkFormat();
|
||||
});
|
||||
|
||||
$( "#BadFormatMessage" ).hide();
|
||||
$( "#AdjacencyMatrixFieldPage" ).hide();
|
||||
|
||||
$( "#showMatrix" ).on('click', function (eventObject)
|
||||
{
|
||||
_ShowMatrixInput();
|
||||
});
|
||||
|
||||
$( "#showText" ).on('click', function (eventObject)
|
||||
{
|
||||
_ShowTextInput();
|
||||
});
|
||||
|
||||
$('input:radio[name="separator"]').change( function(){
|
||||
checkFormat()
|
||||
});
|
||||
|
||||
CopyMatrixToMatrixInput();
|
||||
|
||||
$(document).keydown(function(event) {
|
||||
if (event.which == "17" || event.which == "91")
|
||||
g_ctrlPressed = true;
|
||||
});
|
||||
|
||||
$(document).keyup(function(event) {
|
||||
if (event.which == "17" || event.which == "91")
|
||||
g_ctrlPressed = false;
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<h1><?= L('head_no_tags')?></h1>
|
||||
<p><?= L('text')?></p>
|
||||
|
||||
@ -302,11 +25,11 @@ window.onload = function ()
|
||||
</form>
|
||||
<form action="./" method="post" id="matrixForm">
|
||||
<textarea name="matrix" id="AdjacencyMatrixFieldPage" wrap="off" style="display: none;">
|
||||
<? if (!isset($_GET["matrix"])): ?>
|
||||
<?php if (!isset($_GET["matrix"])): ?>
|
||||
0, 1, 0
|
||||
1, 0, 0
|
||||
0, 1, 0
|
||||
<? else: ?><?= $_GET["matrix"] ?><? endif;?></textarea>
|
||||
<?php else: ?><?= $_GET["matrix"] ?><?php endif;?></textarea>
|
||||
<div id="idSeparatorList" style="display: none;">
|
||||
<?= L('separator') ?>
|
||||
<input type="radio" name="separator" value="commo" id="commoSep" checked> <label for="commoSep"><?= L('separator_commo') ?></label>
|
||||
@ -348,9 +71,6 @@ window.onload = function ()
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<script>
|
||||
CopyMatrixToMatrixInput();
|
||||
</script>
|
||||
|
||||
<? if (L('current_language') == "ru"): ?>
|
||||
<section>
|
||||
|
@ -14,7 +14,7 @@
|
||||
<div class="col-md-4">
|
||||
<div class="thumbnail">
|
||||
<a href="./?graph=<?= $examples[$i]["id"] ?>">
|
||||
<img src="/<? echo (getImageFileName($examples[$i]["id"], true)); ?>" alt="<?= $examples[$i]["title_" . $g_lang["current_language"]] ?>" style="width:100%">
|
||||
<img src="/<?php echo (getImageFileName($examples[$i]["id"], true)); ?>" alt="<?= $examples[$i]["title_" . $g_lang["current_language"]] ?>" style="width:100%">
|
||||
<div class="caption">
|
||||
<p><?= $examples[$i]["title_" . $g_lang["current_language"]] ?></p>
|
||||
</div>
|
||||
|
17
tpl/home.php
17
tpl/home.php
@ -9,9 +9,10 @@
|
||||
<link rel="stylesheet" type="text/css" href="<?= Root('i/css/jquery.feedback_me.css')?>" />
|
||||
|
||||
<script src="<?= Root('i/js/dev/jquery-ui.js')?>"></script>
|
||||
<script src="<?= Root('i/js/dev/jquery.feedback_me.js')?>"></script>
|
||||
<script src="<?= Root("script/canvas2svg.js")?>" ></script>
|
||||
<script src="<?= Root("script/example.js?v=74")?>" ></script>
|
||||
<script src="<?= Root('i/js/dev/jquery.feedback_me.js')?>"></script>
|
||||
|
||||
<script src="<?= RootCacheJS("script/shared/config.js")?>" ></script>
|
||||
<script src="<?= RootCacheJS("script/shared/loader.js")?>" ></script>
|
||||
|
||||
<!-- Yandex.RTB -->
|
||||
<script>window.yaContextCb=window.yaContextCb||[]</script>
|
||||
@ -104,8 +105,8 @@
|
||||
<li> <button type="button" class="btn btn-default btn-sm btn-submenu" id="MoveWorspace"><span class="glyphicon glyphicon-fullscreen fa-fw"></span> <?= L('move_workspace') ?> </button> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default btn-sm" id="Default"><span class="glyphicon glyphicon-fullscreen fa-fw"></span><span class="hidden-phone"> <?= L('default')?> <sub style="color:#AAAAAA">m</sub></span></button>
|
||||
<button type="button" class="btn btn-primary btn-sm" id="AddGraph"><span class="glyphicon glyphicon-plus fa-fw"></span><span class="hidden-phone"> <?= L('add_node')?> <sub style="color:#AAAAAA">v</sub></span></button>
|
||||
<button type="button" class="btn btn-primary btn-sm" id="Default"><span class="glyphicon glyphicon-fullscreen fa-fw"></span><span class="hidden-phone"> <?= L('default')?> <sub style="color:#AAAAAA">m</sub></span></button>
|
||||
<button type="button" class="btn btn-default btn-sm" id="AddGraph"><span class="glyphicon glyphicon-plus fa-fw"></span><span class="hidden-phone"> <?= L('add_node')?> <sub style="color:#AAAAAA">v</sub></span></button>
|
||||
<button type="button" class="btn btn-default btn-sm" id="ConnectGraphs"><span class="glyphicon glyphicon-road fa-fw"></span><span class="hidden-phone"> <?= L('connect_nodes')?> <sub style="color:#AAAAAA">e</sub></span></button>
|
||||
|
||||
<!-- Algorithms -->
|
||||
@ -278,10 +279,10 @@
|
||||
|
||||
<?php else: ?>
|
||||
<section style="height:32px;text-align: center;" id="bottom_info" class="hidden-phone">
|
||||
<a class="ProgresssBarLink" href="opensource" target="_blank">
|
||||
<a class="ProgresssBarLink" href="mailto:admin@graphonline.ru" target="_blank">
|
||||
<div class="ProgressBar" style="height:32px">
|
||||
<div class="ProgressBarFill" style="width:0%;"></div>
|
||||
<span class="ProgressBarText" style="top:-28px"><p><?= L('opensource_message')?></p></span>
|
||||
<span class="ProgressBarText" style="top:-28px"><p><?= L('we_are_improving')?></p></span>
|
||||
</div>
|
||||
</a>
|
||||
</section>
|
||||
@ -892,6 +893,8 @@
|
||||
<p id="wrongImageFormatPNGAndJPEG" class="translation"><?= L('wrong_image_background_format')?></p>
|
||||
<p id="wrongImageSizeP1" class="translation"><?= L('wrong_image_background_size')?></p>
|
||||
</section>
|
||||
|
||||
<script src="<?= RootCacheJS("script/pages/editor/api/index.js")?>" ></script>
|
||||
<!--
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
|
Loading…
x
Reference in New Issue
Block a user