Add new shapes for vertexes.

This commit is contained in:
Oleg Sh 2021-04-15 14:18:47 +02:00
parent 2172acb28f
commit b60e70c089
5 changed files with 230 additions and 13 deletions

View File

@ -151,17 +151,26 @@ BaseEdge.prototype.GetEdgePositionsShift = function()
BaseEdge.prototype.GetEdgePositions = function() 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 position1 = this.vertex1.position;
var position2 = this.vertex2.position; var position2 = this.vertex2.position;
var diameter1 = this.vertex1.model.diameter + parseInt(this.vertex1.currentStyle.lineWidth); var diameter1 = this.vertex1.model.diameter + parseInt(this.vertex1.currentStyle.GetStyle({}).lineWidth);
var diameter2 = this.vertex2.model.diameter + parseInt(this.vertex2.currentStyle.lineWidth); var diameter2 = this.vertex2.model.diameter + parseInt(this.vertex2.currentStyle.GetStyle({}).lineWidth);
var direction = position1.subtract(position2); var direction = position1.subtract(position2);
var direction1 = direction; var direction1 = direction;
var direction2 = direction; var direction2 = direction;
var d1 = diameter1; var d1 = diameter1;
var d2 = -diameter2; var d2 = diameter2;
if (this.model.type == EdgeModels.cruvled) if (this.model.type == EdgeModels.cruvled)
{ {
@ -174,15 +183,47 @@ BaseEdge.prototype.GetEdgePositions = function()
d2 = diameter2; d2 = diameter2;
} }
else
{
direction2 = direction2.multiply(-1);
}
direction1.normalize(1.0); direction1.normalize(1.0);
direction1 = direction1.multiply(0.5);
direction2.normalize(1.0); direction2.normalize(1.0);
direction2 = direction2.multiply(0.5);
var res = []; var vertexes = [];
res.push(position1.subtract(direction1.multiply(d1))); vertexes.push({vertex : this.vertex1, direction : direction1, position : position1, diameter : d1});
res.push(position2.subtract(direction2.multiply(d2))); vertexes.push({vertex : this.vertex2, direction : direction2, position : position2, diameter : d2});
vertexes.forEach(function(data)
{
var shape = data.vertex.currentStyle.GetStyle({}).shape;
if (shape == VertexCircleShape)
{
var direction = data.direction.multiply(0.5);
res.push(data.position.subtract(direction.multiply(data.diameter)));
}
else if (shape == VertexSquareShape || shape == VertexTriangleShape)
{
var lineFinish1 = data.direction.multiply(-1).multiply(1000.0);
var pointsVertex1 = shape == VertexSquareShape ? GetSquarePoints(data.diameter) : GetTrianglePoints(data.diameter);
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; return res;
} }

View File

@ -77,3 +77,46 @@ BaseVertex.prototype.IsUndefinedPosition = function ()
{ {
return this.hasUndefinedPosition; return this.hasUndefinedPosition;
} }
BaseVertex.prototype.HitTest = function (pos)
{
var shape = this.hasOwnProperty('currentStyle') ? this.currentStyle.GetStyle({}).shape : VertexCircleShape;
var width = this.hasOwnProperty('currentStyle') ? this.currentStyle.GetStyle({}).lineWidth : 0;
if (shape == VertexCircleShape)
{
return this.position.distance(pos) < this.model.diameter / 2.0 + width;
}
else if (shape == VertexSquareShape || shape == VertexTriangleShape)
{
var relativPos = (new Point(pos.x, pos.y)).subtract(this.position);
var lineFinish1 = relativPos.add(new Point(1000, 0));
var lineFinish2 = relativPos.add(new Point(-1000, 0));
var pointsVertex1 = shape == VertexSquareShape ? GetSquarePoints(this.model.diameter + width) : GetTrianglePoints(this.model.diameter + width);
pointsVertex1.push(pointsVertex1[0]);
var hitNumber1 = 0;
var hitNumber2 = 0;
console.log("Points");
for (var i = 0; i < pointsVertex1.length - 1; i ++)
{
console.log(pointsVertex1[i] + " " + pointsVertex1[i + 1]);
var hitTest = Point.hitTest(relativPos, lineFinish1, pointsVertex1[i], pointsVertex1[i + 1]);
if (hitTest != null)
{
hitNumber1++;
}
hitTest = Point.hitTest(relativPos, lineFinish2, pointsVertex1[i], pointsVertex1[i + 1]);
if (hitTest != null)
{
hitNumber2++;
}
}
return hitNumber1 == 1 && hitNumber2 == 1;
}
return false;
}

View File

@ -4,6 +4,41 @@
// Test graph: http://localhost:8080/?graph=oimDPgsdgiAjWGBHZZcst // Test graph: http://localhost:8080/?graph=oimDPgsdgiAjWGBHZZcst
// Vertex shape
const VertexCircleShape = 0,
VertexSquareShape = 1,
VertexTriangleShape = 2;
function GetSquarePoints(diameter)
{
var res = [];
var a = diameter;
res.push(new Point(-a / 2, - a / 2));
res.push(new Point(a / 2, -a / 2));
res.push(new Point(a / 2, a / 2));
res.push(new Point(-a / 2, a / 2));
return res;
}
function GetTrianglePoints(diameter)
{
var res = [];
var effectiveDiameter = diameter * 1.5;
var upOffset = effectiveDiameter / 2;
var downOffset = effectiveDiameter / 4;
var lrOffset = effectiveDiameter * 3 / (Math.sqrt(3) * 4);
res.push(new Point(0, - upOffset));
res.push(new Point(lrOffset, downOffset));
res.push(new Point(- lrOffset, downOffset));
return res;
}
function BaseVertexStyle() function BaseVertexStyle()
{ {
this.baseStyles = []; this.baseStyles = [];
@ -24,7 +59,10 @@ BaseVertexStyle.prototype.GetStyle = function (baseStyle)
baseStyle.fillStyle = this.fillStyle; baseStyle.fillStyle = this.fillStyle;
if (this.hasOwnProperty('mainTextColor')) if (this.hasOwnProperty('mainTextColor'))
baseStyle.mainTextColor = this.mainTextColor; baseStyle.mainTextColor = this.mainTextColor;
if (this.hasOwnProperty('shape'))
baseStyle.shape = this.shape;
baseStyle.lineWidth = parseInt(baseStyle.lineWidth);
return baseStyle; return baseStyle;
} }
@ -42,6 +80,7 @@ function CommonVertexStyle()
this.strokeStyle = '#c7b7c7'; this.strokeStyle = '#c7b7c7';
this.fillStyle = '#68aeba'; this.fillStyle = '#68aeba';
this.mainTextColor = '#f0d543'; this.mainTextColor = '#f0d543';
this.shape = VertexCircleShape;//VertexSquareShape;
this.baseStyles = []; this.baseStyles = [];
} }
@ -219,7 +258,10 @@ BaseVertexDrawer.prototype.Draw = function(baseGraph, graphStyle)
{ {
this.SetupStyle(graphStyle); this.SetupStyle(graphStyle);
this.DrawShape(baseGraph); this.DrawShape(baseGraph);
if (this.currentStyle.lineWidth != 0)
this.context.stroke(); this.context.stroke();
this.context.fill(); this.context.fill();
this.DrawCenterText(baseGraph.position, baseGraph.mainText, graphStyle.mainTextColor, graphStyle.fillStyle, true, true, 16); this.DrawCenterText(baseGraph.position, baseGraph.mainText, graphStyle.mainTextColor, graphStyle.fillStyle, true, true, 16);
@ -236,6 +278,7 @@ BaseVertexDrawer.prototype.Draw = function(baseGraph, graphStyle)
BaseVertexDrawer.prototype.SetupStyle = function(style) BaseVertexDrawer.prototype.SetupStyle = function(style)
{ {
this.currentStyle = style;
this.context.lineWidth = style.lineWidth; this.context.lineWidth = style.lineWidth;
this.context.strokeStyle = style.strokeStyle; this.context.strokeStyle = style.strokeStyle;
this.context.fillStyle = style.fillStyle; this.context.fillStyle = style.fillStyle;
@ -244,7 +287,35 @@ BaseVertexDrawer.prototype.SetupStyle = function(style)
BaseVertexDrawer.prototype.DrawShape = function(baseGraph) BaseVertexDrawer.prototype.DrawShape = function(baseGraph)
{ {
this.context.beginPath(); this.context.beginPath();
if (this.currentStyle.shape == VertexCircleShape)
{
this.context.arc(baseGraph.position.x, baseGraph.position.y, baseGraph.model.diameter / 2.0, 0, 2 * Math.PI); this.context.arc(baseGraph.position.x, baseGraph.position.y, baseGraph.model.diameter / 2.0, 0, 2 * Math.PI);
}
else if (this.currentStyle.shape == VertexSquareShape)
{
var points = GetSquarePoints(baseGraph.model.diameter);
this.context.moveTo(baseGraph.position.x + points[points.length - 1].x, baseGraph.position.y + points[points.length - 1].y);
var context = this.context;
points.forEach(function(point) {
context.lineTo(baseGraph.position.x + point.x, baseGraph.position.y + point.y);
});
}
else if (this.currentStyle.shape == VertexTriangleShape)
{
var points = GetTrianglePoints(baseGraph.model.diameter)
this.context.moveTo(baseGraph.position.x + points[points.length - 1].x, baseGraph.position.y + points[points.length - 1].y);
var context = this.context;
points.forEach(function(point) {
context.lineTo(baseGraph.position.x + point.x, baseGraph.position.y + point.y);
});
}
this.context.closePath(); this.context.closePath();
} }

View File

@ -45,7 +45,7 @@ BaseHandler.prototype.GetSelectedGraph = function(pos)
var res = null; var res = null;
for (var i = 0; i < this.app.graph.vertices.length; i ++) for (var i = 0; i < this.app.graph.vertices.length; i ++)
{ {
if (this.app.graph.vertices[i].position.distance(pos) < this.app.graph.vertices[i].model.diameter / 2.0) if (this.app.graph.vertices[i].HitTest(pos))
{ {
// Select last of them. // Select last of them.
res = this.app.graph.vertices[i]; res = this.app.graph.vertices[i];
@ -1376,7 +1376,7 @@ SetupVertexStyle.prototype.show = function(index)
style.mainTextColor = $( "#vertexTextColor" ).val(); style.mainTextColor = $( "#vertexTextColor" ).val();
if (fullStyle.lineWidth != $( "#vertexStrokeSize" ).val()) if (fullStyle.lineWidth != $( "#vertexStrokeSize" ).val())
style.lineWidth = $( "#vertexStrokeSize" ).val(); style.lineWidth = parseInt($( "#vertexStrokeSize" ).val());
var canvas = document.getElementById( "VertexPreview" ); var canvas = document.getElementById( "VertexPreview" );
var context = canvas.getContext('2d'); var context = canvas.getContext('2d');

View File

@ -96,6 +96,11 @@ Point.prototype.inverse = function()
return new Point(-this.x, -this.y); 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){ 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); return new Point(pt1.x * (1.0 - f) + pt2.x * f, pt1.y * (1.0 - f) + pt2.y * f);
}; };
@ -116,6 +121,63 @@ Point.toString = function(){
return x + " " + y; 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)
{ // a(y)
var q = (x2 - x1) / (y1 - y2);
var sn = (x3 - x4) + (y3 - y4) * q;
if (sn == 0.0)
{
return res;
} // c(x) + c(y)*q
var fn = (x3 - x1) + (y3 - y1) * q; // b(x) + b(y)*q
n = fn / sn;
}
else
{
if ((y3 - y4) == 0.0)
{
return res;
} // b(y)
n = (y3 - y1) / (y3 - y4); // c(y)/b(y)
}
// x3 + (-b(x))*n && y3 +(-b(y))*n
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){ function Rect(minPoint, maxPoint){
this.minPoint = minPoint; this.minPoint = minPoint;
this.maxPoint = maxPoint; this.maxPoint = maxPoint;