mirror of
https://github.com/UnickSoft/graphonline.git
synced 2025-07-01 23:36:00 +00:00
Added edge bend. Small edges fixes.
This commit is contained in:
parent
94f643f587
commit
b2a80c7f4f
@ -138,4 +138,6 @@
|
||||
|
||||
$g_lang["start_traversal"] = "Select start traversal vertex";
|
||||
$g_lang["traversal_order"] = "Traversal order: ";
|
||||
|
||||
$g_lang["curve_edge"] = "Edge bend";
|
||||
?>
|
||||
|
@ -141,4 +141,6 @@
|
||||
|
||||
$g_lang["start_traversal"] = "Выбирете начальную вершину обхода";
|
||||
$g_lang["traversal_order"] = "Порядок обхода: ";
|
||||
|
||||
$g_lang["curve_edge"] = "Изгиб дуги";
|
||||
?>
|
||||
|
@ -197,9 +197,33 @@ Application.prototype.setRenderPath = function(renderPath)
|
||||
}
|
||||
}
|
||||
|
||||
Application.prototype.RedrawEdge = function(context, edge)
|
||||
Application.prototype.GetBaseArcDrawer = function(context, edge)
|
||||
{
|
||||
var arcDrawer = new BaseEdgeDrawer(context);
|
||||
|
||||
if (edge.model.type == EdgeModels.cruvled)
|
||||
{
|
||||
var curvedArcDrawer = new CurvedArcDrawer(context, edge.model);
|
||||
|
||||
arcDrawer = new BaseEdgeDrawer(context,
|
||||
{
|
||||
drawArc : curvedArcDrawer,
|
||||
startArrowDiretion : curvedArcDrawer,
|
||||
finishArrowDiretion : curvedArcDrawer,
|
||||
textCenterObject : curvedArcDrawer,
|
||||
getPointOnArc : curvedArcDrawer
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return arcDrawer;
|
||||
}
|
||||
|
||||
Application.prototype.RedrawEdge = function(context, edge)
|
||||
{
|
||||
var curvedArcDrawer = new CurvedArcDrawer(context, edge.model)
|
||||
var arcDrawer = this.GetBaseArcDrawer(context, edge);
|
||||
|
||||
var commonStyle = new CommonEdgeStyle(context);
|
||||
var selectedStyles = selectedEdgeStyles;
|
||||
|
||||
@ -222,7 +246,8 @@ Application.prototype._RedrawEdgeWithStyle = function(edge, style, arcDrawer, co
|
||||
|
||||
Application.prototype.RedrawEdgeProgress = function(context, edge, progress)
|
||||
{
|
||||
var arcDrawer = new ProgressArcDrawer(context, new BaseEdgeDrawer(context), progress);
|
||||
var progressDraw = new ProgressArcDrawer(context, this.GetBaseArcDrawer(context, edge), progress);
|
||||
var arcDrawer = new BaseEdgeDrawer(context, {drawObject : progressDraw});
|
||||
var commonStyle = new CommonEdgeStyle(context);
|
||||
var selectedStyles = selectedEdgeStyles;
|
||||
|
||||
@ -237,7 +262,6 @@ Application.prototype.RedrawEdges = function(context)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Application.prototype.RedrawNodes = function(context)
|
||||
{
|
||||
var graphDrawer = new BaseVertexDrawer(context);
|
||||
@ -374,12 +398,38 @@ Application.prototype.CreateNewArc = function(graph1, graph2, isDirect, weight)
|
||||
useWeight = true;
|
||||
}
|
||||
weight = (!isNaN(parseInt(weight, 10)) && weight >= 0) ? weight : 1;
|
||||
return this.AddNewEdge(new BaseEdge(graph1, graph2, isDirect, weight, useWeight));
|
||||
var edge = this.AddNewEdge(new BaseEdge(graph1, graph2, isDirect, weight, useWeight));
|
||||
|
||||
// Make cruvled for pair.
|
||||
var edgeObject = this.graph.edges[edge];
|
||||
if (edgeObject.hasPair)
|
||||
{
|
||||
if (edgeObject.model.default)
|
||||
edgeObject.model.type = EdgeModels.cruvled;
|
||||
|
||||
var pairEdge = this.FindEdge(graph2.id, graph1.id);
|
||||
if (pairEdge.model.default)
|
||||
pairEdge.model.type = EdgeModels.cruvled;
|
||||
}
|
||||
|
||||
return edge;
|
||||
}
|
||||
|
||||
Application.prototype.DeleteEdge = function(edgeObject)
|
||||
{
|
||||
var vertex1 = edgeObject.vertex1;
|
||||
var vertex2 = edgeObject.vertex2;
|
||||
var hasPair = edgeObject.hasPair;
|
||||
|
||||
this.graph.DeleteEdge(edgeObject);
|
||||
|
||||
// Make line for pair.
|
||||
if (hasPair)
|
||||
{
|
||||
var edgeObject = this.FindEdge(vertex2.id, vertex1.id);
|
||||
if (edgeObject.model.default)
|
||||
edgeObject.model.type = EdgeModels.line;
|
||||
}
|
||||
}
|
||||
|
||||
Application.prototype.DeleteVertex = function(graphObject)
|
||||
|
@ -34,6 +34,7 @@ BaseEdge.prototype.SaveToXML = function ()
|
||||
"text=\"" + this.text + "\" " +
|
||||
"arrayStyleStart=\"" + this.arrayStyleStart + "\" " +
|
||||
"arrayStyleFinish=\"" + this.arrayStyleFinish + "\" " +
|
||||
this.model.SaveToXML() +
|
||||
"></edge>";
|
||||
}
|
||||
|
||||
@ -51,6 +52,8 @@ BaseEdge.prototype.LoadFromXML = function (xml, graph)
|
||||
this.text = xml.attr("text") == null ? "" : xml.attr("text");
|
||||
this.arrayStyleStart = xml.attr("arrayStyleStart") == null ? "" : xml.attr("arrayStyleStart");
|
||||
this.arrayStyleFinish = xml.attr("arrayStyleFinish") == null ? "" : xml.attr("arrayStyleFinish");
|
||||
|
||||
this.model.LoadFromXML(xml);
|
||||
}
|
||||
|
||||
BaseEdge.prototype.GetPixelLength = function ()
|
||||
@ -84,3 +87,77 @@ 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()
|
||||
{
|
||||
var pairShift = this.vertex1.model.diameter * 0.25;
|
||||
var shift = (this.hasPair ? pairShift : 0);
|
||||
|
||||
if (shift == 0 || this.model.type == EdgeModels.cruvled)
|
||||
{
|
||||
return this.GetEdgePositions();
|
||||
}
|
||||
else
|
||||
{
|
||||
var position1 = this.vertex1.position;
|
||||
var position2 = this.vertex2.position;
|
||||
var diameter1 = this.vertex1.model.diameter;
|
||||
var diameter2 = this.vertex2.model.diameter;
|
||||
|
||||
var direction = position1.subtract(position2);
|
||||
direction.normalize(1.0);
|
||||
var normal = direction.normal();
|
||||
direction = direction.multiply(0.5);
|
||||
position1 = position1.subtract(normal.multiply(shift));
|
||||
position2 = position2.subtract(normal.multiply(shift));
|
||||
diameter1 = Math.sqrt(diameter1 * diameter1 - shift * shift);
|
||||
diameter2 = Math.sqrt(diameter2 * diameter2 - shift * shift);
|
||||
var res = [];
|
||||
res.push(position1.subtract(direction.multiply(diameter1)));
|
||||
res.push(position2.subtract(direction.multiply(-diameter2)));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
BaseEdge.prototype.GetEdgePositions = function()
|
||||
{
|
||||
var position1 = this.vertex1.position;
|
||||
var position2 = this.vertex2.position;
|
||||
var diameter1 = this.vertex1.model.diameter;
|
||||
var diameter2 = this.vertex2.model.diameter;
|
||||
|
||||
var direction = position1.subtract(position2);
|
||||
|
||||
var direction1 = direction;
|
||||
var direction2 = direction;
|
||||
var d1 = diameter1;
|
||||
var d2 = -diameter2;
|
||||
|
||||
if (this.model.type == EdgeModels.cruvled)
|
||||
{
|
||||
var dist = position1.distance(position2);
|
||||
var point1 = this.model.GetCurvedPoint(position1, position2, 10.0 / dist);
|
||||
direction1 = position1.subtract(point1);
|
||||
|
||||
var point2 = this.model.GetCurvedPoint(position1, position2, 1.0 - 10.0 / dist);
|
||||
direction2 = position2.subtract(point2);
|
||||
|
||||
d2 = diameter2;
|
||||
}
|
||||
|
||||
direction1.normalize(1.0);
|
||||
direction1 = direction1.multiply(0.5);
|
||||
direction2.normalize(1.0);
|
||||
direction2 = direction2.multiply(0.5);
|
||||
|
||||
var res = [];
|
||||
res.push(position1.subtract(direction1.multiply(d1)));
|
||||
res.push(position2.subtract(direction2.multiply(d2)));
|
||||
return res;
|
||||
}
|
@ -14,7 +14,6 @@ function CommonEdgeStyle()
|
||||
this.loopShiftAngel = Math.PI / 6;
|
||||
}
|
||||
|
||||
|
||||
function SelectedEdgeStyle0()
|
||||
{
|
||||
CommonEdgeStyle.apply(this, arguments);
|
||||
@ -83,42 +82,67 @@ var selectedEdgeStyles = [new SelectedEdgeStyle0(), new SelectedEdgeStyle1(),
|
||||
new SelectedEdgeStyle2(), new SelectedEdgeStyle3(), new SelectedEdgeStyle4()];
|
||||
|
||||
|
||||
function BaseEdgeDrawer(context)
|
||||
function BaseEdgeDrawer(context, drawObjects = null)
|
||||
{
|
||||
this.context = context;
|
||||
|
||||
this.drawObject = null;
|
||||
this.drawArc = null;
|
||||
this.startArrowDiretion = null;
|
||||
this.finishArrowDiretion = null;
|
||||
this.textCenterObject = null;
|
||||
this.getPointOnArc = null;
|
||||
|
||||
if (drawObjects)
|
||||
{
|
||||
if (drawObjects.hasOwnProperty("drawObject"))
|
||||
this.drawObject = drawObjects.drawObject;
|
||||
if (drawObjects.hasOwnProperty("drawArc"))
|
||||
this.drawArc = drawObjects.drawArc;
|
||||
if (drawObjects.hasOwnProperty("startArrowDiretion"))
|
||||
this.startArrowDiretion = drawObjects.startArrowDiretion;
|
||||
if (drawObjects.hasOwnProperty("finishArrowDiretion"))
|
||||
this.finishArrowDiretion = drawObjects.finishArrowDiretion;
|
||||
if (drawObjects.hasOwnProperty("textCenterObject"))
|
||||
this.textCenterObject = drawObjects.textCenterObject;
|
||||
if (drawObjects.hasOwnProperty("getPointOnArc"))
|
||||
this.getPointOnArc = drawObjects.getPointOnArc;
|
||||
}
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.Draw = function(baseEdge, arcStyle)
|
||||
{
|
||||
if (this.drawObject && this.drawObject != this)
|
||||
{
|
||||
this.drawObject.Draw(baseEdge, arcStyle);
|
||||
return;
|
||||
}
|
||||
|
||||
this.SetupStyle(baseEdge, arcStyle);
|
||||
|
||||
var length = baseEdge.model.width * 4;
|
||||
var width = baseEdge.model.width * 2;
|
||||
var lengthArrow = baseEdge.model.width * 4;
|
||||
var widthArrow = baseEdge.model.width * 2;
|
||||
var position1 = baseEdge.vertex1.position;
|
||||
var position2 = baseEdge.vertex2.position;
|
||||
var direction = position1.subtract(position2);
|
||||
var pairShift = baseEdge.vertex1.model.diameter * 0.25;
|
||||
var realShift = (baseEdge.hasPair ? pairShift : 0);
|
||||
direction.normalize(1.0);
|
||||
var positions = this.GetArcPositionsShift(baseEdge.vertex1.position,
|
||||
baseEdge.vertex2.position, baseEdge.vertex1.model.diameter, baseEdge.vertex2.model.diameter, realShift);
|
||||
var positions = baseEdge.GetEdgePositionsShift();
|
||||
|
||||
var hasStartStyle = !position1.equals(position2) && baseEdge.GetStartEdgeStyle() != "";
|
||||
var hasStartStyle = !position1.equals(position2) && baseEdge.GetStartEdgeStyle() != "";
|
||||
var hasFinishStyle = !position1.equals(position2) && baseEdge.GetFinishEdgeStyle() != "";
|
||||
|
||||
this.DrawArc (positions[0].subtract(direction.multiply(hasStartStyle ? -length / 2 : 0.0)),
|
||||
positions[1].subtract(direction.multiply(hasFinishStyle ? -length / 2 : 0.0)), arcStyle);
|
||||
this.DrawArc (positions[0], positions[1], arcStyle);
|
||||
|
||||
this.context.fillStyle = this.context.strokeStyle;
|
||||
this.context.lineWidth = 0;
|
||||
|
||||
if (hasStartStyle)
|
||||
{
|
||||
this.DrawArrow(positions[0], positions[1], length, width);
|
||||
this.DrawArrow(positions[0], this.GetStartArrowDiretion(positions[0], positions[1], lengthArrow), lengthArrow, widthArrow);
|
||||
}
|
||||
if (hasFinishStyle)
|
||||
{
|
||||
this.DrawArrow(positions[1], positions[0], length, width);
|
||||
this.DrawArrow(positions[1], this.GetFinishArrowDiretion(positions[0], positions[1], lengthArrow), lengthArrow, widthArrow);
|
||||
}
|
||||
|
||||
this.SetupStyle(baseEdge, arcStyle);
|
||||
@ -140,6 +164,12 @@ BaseEdgeDrawer.prototype.SetupStyle = function(baseEdge, arcStyle)
|
||||
|
||||
BaseEdgeDrawer.prototype.DrawArc = function(position1, position2, arcStyle)
|
||||
{
|
||||
if (this.drawArc && this.drawArc != this)
|
||||
{
|
||||
this.drawArc.DrawArc(position1, position2, arcStyle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (position1.equals(position2))
|
||||
{
|
||||
this.context.beginPath();
|
||||
@ -160,13 +190,8 @@ BaseEdgeDrawer.prototype.DrawArc = function(position1, position2, arcStyle)
|
||||
|
||||
BaseEdgeDrawer.prototype.DrawWeight = function(position1, position2, text, arcStyle, hasPair)
|
||||
{
|
||||
var textShift = Math.min(12 / position1.subtract(position2).length(), 0.4);
|
||||
var centerPoint = Point.interpolate(position1, position2, 0.5 + (hasPair ? textShift : 0));
|
||||
if (position1.equals(position2))
|
||||
{
|
||||
centerPoint.y = centerPoint.y - Math.cos(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop * 2;
|
||||
centerPoint.x = centerPoint.x - Math.sin(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop * 2;
|
||||
}
|
||||
var centerPoint = this.GetTextCenterPoint(position1, position2, hasPair, arcStyle);
|
||||
|
||||
this.context.font = "bold 16px sans-serif";
|
||||
this.context.textBaseline = "middle";
|
||||
this.context.lineWidth = arcStyle.textStrockeWidth;
|
||||
@ -186,60 +211,74 @@ BaseEdgeDrawer.prototype.DrawWeight = function(position1, position2, text, arcSt
|
||||
this.context.fillText(text, centerPoint.x - widthText / 2, centerPoint.y);
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.GetArcPositions = function(position1, position2, diameter1, diameter2)
|
||||
BaseEdgeDrawer.prototype.DrawArrow = function(position, direction, length, width)
|
||||
{
|
||||
var direction = position1.subtract(position2);
|
||||
direction.normalize(1.0);
|
||||
direction = direction.multiply(0.5);
|
||||
|
||||
var res = [];
|
||||
res.push(position1.subtract(direction.multiply(diameter1)));
|
||||
res.push(position2.subtract(direction.multiply(-diameter2)));
|
||||
return res;
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.GetArcPositionsShift = function(position1, position2, diameter1, diameter2, shift)
|
||||
{
|
||||
if (shift == 0)
|
||||
{
|
||||
return this.GetArcPositions(position1, position2, diameter1, diameter2);
|
||||
}
|
||||
else
|
||||
{
|
||||
var direction = position1.subtract(position2);
|
||||
direction.normalize(1.0);
|
||||
var normal = direction.normal();
|
||||
direction = direction.multiply(0.5);
|
||||
position1 = position1.subtract(normal.multiply(shift));
|
||||
position2 = position2.subtract(normal.multiply(shift));
|
||||
diameter1 = Math.sqrt(diameter1 * diameter1 - shift * shift);
|
||||
diameter2 = Math.sqrt(diameter2 * diameter2 - shift * shift);
|
||||
var res = [];
|
||||
res.push(position1.subtract(direction.multiply(diameter1)));
|
||||
res.push(position2.subtract(direction.multiply(-diameter2)));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.DrawArrow = function(position1, position2, length, width)
|
||||
{
|
||||
var direction = position1.subtract(position2);
|
||||
direction.normalize(1.0);
|
||||
var normal = direction.normal();
|
||||
|
||||
var pointOnLine = position1.subtract(direction.multiply(length));
|
||||
var pointOnLine = position.subtract(direction.multiply(length));
|
||||
var point1 = pointOnLine.add(normal.multiply(width));
|
||||
var point2 = pointOnLine.add(normal.multiply(-width));
|
||||
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(position1.x, position1.y);
|
||||
this.context.moveTo(position.x, position.y);
|
||||
this.context.lineTo(point1.x, point1.y);
|
||||
this.context.lineTo(point2.x, point2.y);
|
||||
this.context.lineTo(position1.x, position1.y);
|
||||
this.context.lineTo(position.x, position.y);
|
||||
this.context.closePath();
|
||||
this.context.fill();
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.GetStartArrowDiretion = function(position1, position2, lengthArrow)
|
||||
{
|
||||
if (this.startArrowDiretion && this.startArrowDiretion != this)
|
||||
{
|
||||
return this.startArrowDiretion.GetStartArrowDiretion(position1, position2, lengthArrow);
|
||||
}
|
||||
|
||||
var direction = position1.subtract(position2);
|
||||
direction.normalize(1.0);
|
||||
return direction;
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.GetFinishArrowDiretion = function(position1, position2, lengthArrow)
|
||||
{
|
||||
if (this.finishArrowDiretion && this.finishArrowDiretion != this)
|
||||
{
|
||||
return this.finishArrowDiretion.GetFinishArrowDiretion(position1, position2, lengthArrow);
|
||||
}
|
||||
|
||||
var direction = position2.subtract(position1);
|
||||
direction.normalize(1.0);
|
||||
return direction;
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.GetTextCenterPoint = function (position1, position2, hasPair, arcStyle)
|
||||
{
|
||||
if (this.textCenterObject && this.textCenterObject != this)
|
||||
{
|
||||
return this.textCenterObject.GetTextCenterPoint(position1, position2, hasPair, arcStyle);
|
||||
}
|
||||
|
||||
var textShift = Math.min(12 / position1.subtract(position2).length(), 0.4);
|
||||
var centerPoint = Point.interpolate(position1, position2, 0.5 + (hasPair ? textShift : 0));
|
||||
if (position1.equals(position2))
|
||||
{
|
||||
centerPoint.y = centerPoint.y - Math.cos(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop * 2;
|
||||
centerPoint.x = centerPoint.x - Math.sin(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop * 2;
|
||||
}
|
||||
|
||||
return centerPoint;
|
||||
}
|
||||
|
||||
BaseEdgeDrawer.prototype.GetPointOnArc = function (position1, position2, procent)
|
||||
{
|
||||
if (this.getPointOnArc && this.getPointOnArc != this)
|
||||
{
|
||||
return this.getPointOnArc.GetPointOnArc(position1, position2, procent);
|
||||
}
|
||||
|
||||
return Point.interpolate(position1, position2, procent);
|
||||
}
|
||||
|
||||
function ProgressArcDrawer(context, baseDrawer, progress)
|
||||
{
|
||||
@ -259,10 +298,7 @@ ProgressArcDrawer.prototype.Draw = function(baseEdge, arcStyle)
|
||||
|
||||
this.context.lineWidth = 10;
|
||||
|
||||
var pairShift = baseEdge.vertex1.model.diameter * 0.25;
|
||||
var realShift = (baseEdge.hasPair ? pairShift : 0);
|
||||
var positions = this.GetArcPositionsShift(baseEdge.vertex1.position,
|
||||
baseEdge.vertex2.position, baseEdge.vertex1.model.diameter, baseEdge.vertex2.model.diameter, realShift);
|
||||
var positions = baseEdge.GetEdgePositionsShift();
|
||||
var progressSize = 10;
|
||||
|
||||
if (positions[0].equals(positions[1]))
|
||||
@ -277,8 +313,8 @@ ProgressArcDrawer.prototype.Draw = function(baseEdge, arcStyle)
|
||||
}
|
||||
else
|
||||
{
|
||||
var startPosition = Point.interpolate(positions[0], positions[1], this.progress);
|
||||
var vectorOffset = positions[0].subtract(positions[1]).normalizeCopy(progressSize);
|
||||
var startPosition = this.baseDrawer.GetPointOnArc(positions[0], positions[1], this.progress);
|
||||
var vectorOffset = positions[0].subtract(positions[1]).normalizeCopy(progressSize);
|
||||
var finishPosition = startPosition.add(vectorOffset);
|
||||
|
||||
this.context.beginPath();
|
||||
@ -290,7 +326,66 @@ ProgressArcDrawer.prototype.Draw = function(baseEdge, arcStyle)
|
||||
}
|
||||
|
||||
|
||||
function CurvedArcDrawer(context, model)
|
||||
{
|
||||
this.context = context;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
CurvedArcDrawer.prototype = Object.create(BaseEdgeDrawer.prototype);
|
||||
|
||||
CurvedArcDrawer.prototype.DrawArc = function(position1, position2, arcStyle)
|
||||
{
|
||||
if (position1.equals(position2))
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.arc(position1.x - Math.cos(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop,
|
||||
position1.y - Math.sin(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop, arcStyle.sizeOfLoop, 0, 2 * Math.PI);
|
||||
this.context.closePath();
|
||||
this.context.stroke();
|
||||
}
|
||||
else
|
||||
{
|
||||
var points = this.model.GetBezierPoints(position1, position2);
|
||||
var firstBezierPoint = points[0];
|
||||
var secondBezierPoint = points[1];
|
||||
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(position1.x, position1.y);
|
||||
this.context.bezierCurveTo(firstBezierPoint.x, firstBezierPoint.y, secondBezierPoint.x, secondBezierPoint.y, position2.x, position2.y);
|
||||
this.context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
CurvedArcDrawer.prototype.GetStartArrowDiretion = function(position1, position2, lengthArrow)
|
||||
{
|
||||
var dist = position1.distance(position2);
|
||||
var direction = position1.subtract(this.model.GetCurvedPoint(position1, position2, lengthArrow / dist));
|
||||
direction.normalize(1.0);
|
||||
return direction;
|
||||
}
|
||||
|
||||
CurvedArcDrawer.prototype.GetFinishArrowDiretion = function(position1, position2, lengthArrow)
|
||||
{
|
||||
var dist = position1.distance(position2);
|
||||
var direction = position2.subtract(this.model.GetCurvedPoint(position1, position2, 1.0 - lengthArrow / dist));
|
||||
direction.normalize(1.0);
|
||||
return direction;
|
||||
}
|
||||
|
||||
CurvedArcDrawer.prototype.GetTextCenterPoint = function (position1, position2, hasPair, arcStyle)
|
||||
{
|
||||
var centerPoint = this.model.GetCurvedPoint(position1, position2, 0.5)
|
||||
if (position1.equals(position2))
|
||||
{
|
||||
centerPoint.y = centerPoint.y - Math.cos(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop * 2;
|
||||
centerPoint.x = centerPoint.x - Math.sin(arcStyle.loopShiftAngel) * arcStyle.sizeOfLoop * 2;
|
||||
}
|
||||
|
||||
return centerPoint;
|
||||
}
|
||||
|
||||
CurvedArcDrawer.prototype.GetPointOnArc = function (position1, position2, procent)
|
||||
{
|
||||
return this.model.GetCurvedPoint(position1, position2, procent);
|
||||
}
|
||||
|
@ -3,7 +3,145 @@
|
||||
*
|
||||
*/
|
||||
|
||||
var EdgeModels = {"line": 0, "cruvled" : 1};
|
||||
|
||||
function EdgeModel()
|
||||
{
|
||||
this.width = 4;
|
||||
this.type = EdgeModels.line;
|
||||
this.curvedValue = EdgeModel.prototype.defaultCruved;
|
||||
this.default = true;
|
||||
}
|
||||
|
||||
EdgeModel.prototype.defaultCruved = 0.1;
|
||||
|
||||
EdgeModel.prototype.SaveToXML = function ()
|
||||
{
|
||||
return "model_width=\"" + this.width + "\" " +
|
||||
"model_type=\"" + this.type + "\" " +
|
||||
"model_curvedValue=\"" + this.curvedValue + "\" "
|
||||
"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.curvedValue = xml.attr('model_curvedValue') == null ? this.curvedValue : parseFloat(xml.attr("model_curvedValue"));
|
||||
this.default = xml.attr('model_default') == null ? this.default : parseFloat(xml.attr("model_default"));
|
||||
}
|
||||
|
||||
EdgeModel.prototype.GetCurvedPoint = 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.curvedValue;
|
||||
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.cruvled)
|
||||
return this.HitTestCurved(position1, position2, mousePos);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
EdgeModel.prototype.HitTestLine = function(position1, position2, mousePos, factor = 1.0)
|
||||
{
|
||||
var pos1 = position1;
|
||||
var pos2 = position2;
|
||||
var pos0 = mousePos;
|
||||
|
||||
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.HitTestCurved = function(position1, position2, mousePos)
|
||||
{
|
||||
var interval_count = position1.distance(position2) / 100 * 30;
|
||||
|
||||
var start = position1;
|
||||
for (var i = 0; i < interval_count; i ++)
|
||||
{
|
||||
var finish = this.GetCurvedPoint(position1, position2, i / interval_count);
|
||||
|
||||
if (this.HitTestLine(start, finish, mousePos, 2.0))
|
||||
return true;
|
||||
|
||||
start = finish;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EdgeModel.prototype.ChangeCurvedValue = function (delta)
|
||||
{
|
||||
if (this.type == EdgeModels.line)
|
||||
{
|
||||
this.type = EdgeModels.cruvled;
|
||||
this.curvedValue = 0.0;
|
||||
}
|
||||
|
||||
this.curvedValue = this.curvedValue + delta;
|
||||
|
||||
if (Math.abs(this.curvedValue) <= 0.01)
|
||||
this.type = EdgeModels.line;
|
||||
|
||||
this.default = false;
|
||||
}
|
||||
|
@ -57,26 +57,10 @@ BaseHandler.prototype.GetSelectedArc = function(pos)
|
||||
// Selected Arc.
|
||||
for (var i = 0; i < this.app.graph.edges.length; i ++)
|
||||
{
|
||||
var pos1 = this.app.graph.edges[i].vertex1.position;
|
||||
var pos2 = this.app.graph.edges[i].vertex2.position;
|
||||
var pos0 = new Point(pos.x, pos.y);
|
||||
|
||||
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.app.graph.edges[i].model.width * 1.5)
|
||||
{
|
||||
return this.app.graph.edges[i];
|
||||
}
|
||||
}
|
||||
var edge = this.app.graph.edges[i];
|
||||
|
||||
if (edge.HitTest(new Point(pos.x, pos.y)))
|
||||
return edge;
|
||||
}
|
||||
|
||||
|
||||
@ -217,9 +201,10 @@ function DefaultHandler(app)
|
||||
{
|
||||
BaseHandler.apply(this, arguments);
|
||||
this.message = g_textsSelectAndMove;
|
||||
|
||||
this.bindedRename = false;
|
||||
}
|
||||
|
||||
|
||||
// inheritance.
|
||||
DefaultHandler.prototype = Object.create(BaseHandler.prototype);
|
||||
// Current drag object.
|
||||
@ -230,10 +215,8 @@ DefaultHandler.prototype.selectedObject = null;
|
||||
DefaultHandler.prototype.pressed = false;
|
||||
// Prev position.
|
||||
DefaultHandler.prototype.prevPosition = false;
|
||||
// Is binded event for rename
|
||||
DefaultHandler.prototype.bindedRename = false;
|
||||
// Is binded event for edit edge
|
||||
DefaultHandler.prototype.editEdgeRename = false;
|
||||
// Cuvled change value.
|
||||
DefaultHandler.prototype.curvedValue = 0.1;
|
||||
|
||||
DefaultHandler.prototype.MouseMove = function(pos)
|
||||
{
|
||||
@ -307,48 +290,58 @@ DefaultHandler.prototype.MouseUp = function(pos)
|
||||
}
|
||||
else if (this.selectedObject != null && (this.selectedObject instanceof BaseEdge))
|
||||
{
|
||||
this.message = g_textsSelectAndMove + " <button type=\"button\" id=\"editEdge\" class=\"btn btn-default btn-xs\" style=\"float:right;z-index:1;position: relative;\">" + g_editWeight + "</button>";
|
||||
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>"
|
||||
+ "   <button type=\"button\" id=\"editEdge\" class=\"btn btn-default btn-xs\" style=\"z-index:1;position: relative;\">" + g_editWeight + "</button></span>";
|
||||
var handler = this;
|
||||
if (!this.editEdgeRename)
|
||||
{
|
||||
$('#message').unbind();
|
||||
$('#message').on('click', '#editEdge', function(){
|
||||
var direct = false;
|
||||
var dialogButtons = {};
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
|
||||
handler.app.DeleteObject(handler.selectedObject);
|
||||
handler.selectedObject = handler.app.graph.edges[handler.app.CreateNewArc(handler.selectedObject.vertex1, handler.selectedObject.vertex2, handler.selectedObject.isDirect, document.getElementById('EdgeWeight').value)];
|
||||
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
|
||||
userAction("ChangeWeight");
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
document.getElementById('EdgeWeight').value = handler.selectedObject.useWeight ? handler.selectedObject.weight : g_noWeight;
|
||||
document.getElementById('EdgeWeightSlider').value = handler.selectedObject.useWeight ? handler.selectedObject.weight : 0;
|
||||
|
||||
$( "#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;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.editEdgeRename = true;
|
||||
}
|
||||
$('#message').unbind();
|
||||
$('#message').on('click', '#editEdge', function(){
|
||||
var direct = false;
|
||||
var dialogButtons = {};
|
||||
|
||||
dialogButtons[g_save] = function() {
|
||||
|
||||
handler.app.DeleteObject(handler.selectedObject);
|
||||
handler.selectedObject = handler.app.graph.edges[handler.app.CreateNewArc(handler.selectedObject.vertex1, handler.selectedObject.vertex2, handler.selectedObject.isDirect, document.getElementById('EdgeWeight').value)];
|
||||
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
|
||||
userAction("ChangeWeight");
|
||||
$( this ).dialog( "close" );
|
||||
};
|
||||
|
||||
document.getElementById('EdgeWeight').value = handler.selectedObject.useWeight ? handler.selectedObject.weight : g_noWeight;
|
||||
document.getElementById('EdgeWeightSlider').value = handler.selectedObject.useWeight ? handler.selectedObject.weight : 0;
|
||||
|
||||
$( "#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;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#message').on('click', '#incCurvel', function(){
|
||||
handler.selectedObject.model.ChangeCurvedValue(DefaultHandler.prototype.curvedValue);
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
});
|
||||
$('#message').on('click', '#decCurvel', function(){
|
||||
handler.selectedObject.model.ChangeCurvedValue(-DefaultHandler.prototype.curvedValue);
|
||||
handler.needRedraw = true;
|
||||
handler.app.redrawGraph();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,10 +90,10 @@ Graph.prototype.DeleteEdge = function(edgeObject)
|
||||
var index = this.edges.indexOf(edgeObject);
|
||||
if (index > -1)
|
||||
{
|
||||
var edgeRevert = this.FindEdge(edgeObject.vertex2, edgeObject.vertex1);
|
||||
var edgeRevert = this.FindEdge(edgeObject.vertex2.id, edgeObject.vertex1.id);
|
||||
if (edgeRevert != null && edgeRevert.isDirect)
|
||||
{
|
||||
edgeRevert.isPair = false;
|
||||
edgeRevert.hasPair = false;
|
||||
}
|
||||
this.edges.splice(index, 1);
|
||||
}
|
||||
|
@ -95,6 +95,8 @@ var g_hasNotHamiltonianPath = "Graph has not Hamiltonian Path";
|
||||
var g_startTraversal = "Select start traversal vector";
|
||||
var g_traversalOrder = "Traversal order: ";
|
||||
|
||||
var g_curveEdge = "Curved edge";
|
||||
|
||||
function loadTexts()
|
||||
{
|
||||
g_textsSelectAndMove = document.getElementById("SelectAndMoveObject").innerHTML;
|
||||
@ -189,4 +191,6 @@ function loadTexts()
|
||||
|
||||
g_startTraversal = document.getElementById("startTraversal").innerHTML;
|
||||
g_traversalOrder = document.getElementById("traversalOrder").innerHTML;
|
||||
|
||||
g_curveEdge = document.getElementById("curveEdge").innerHTML;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<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/example.js?v=13")?>" ></script>
|
||||
<script src="<?= Root("script/example.js?v=14")?>" ></script>
|
||||
</head>
|
||||
<!--
|
||||
<div class="pull-right">
|
||||
@ -428,6 +428,8 @@
|
||||
|
||||
<p id="startTraversal" class="translation"><?= L('start_traversal')?></p>
|
||||
<p id="traversalOrder" class="translation"><?= L('traversal_order')?></p>
|
||||
|
||||
<p id="curveEdge" class="translation"><?= L('curve_edge')?></p>
|
||||
</section>
|
||||
<!--
|
||||
<script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user