922 lines
20 KiB
JavaScript
922 lines
20 KiB
JavaScript
/**
|
|
* Copyright (c) 2006-2015, JGraph Ltd
|
|
* Copyright (c) 2006-2015, Gaudenz Alder
|
|
*/
|
|
var mxPerimeter =
|
|
{
|
|
/**
|
|
* Class: mxPerimeter
|
|
*
|
|
* Provides various perimeter functions to be used in a style
|
|
* as the value of <mxConstants.STYLE_PERIMETER>. Perimeters for
|
|
* rectangle, circle, rhombus and triangle are available.
|
|
*
|
|
* Example:
|
|
*
|
|
* (code)
|
|
* <add as="perimeter">mxPerimeter.RectanglePerimeter</add>
|
|
* (end)
|
|
*
|
|
* Or programmatically:
|
|
*
|
|
* (code)
|
|
* style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
|
|
* (end)
|
|
*
|
|
* When adding new perimeter functions, it is recommended to use the
|
|
* mxPerimeter-namespace as follows:
|
|
*
|
|
* (code)
|
|
* mxPerimeter.CustomPerimeter = function (bounds, vertex, next, orthogonal)
|
|
* {
|
|
* var x = 0; // Calculate x-coordinate
|
|
* var y = 0; // Calculate y-coordainte
|
|
*
|
|
* return new mxPoint(x, y);
|
|
* }
|
|
* (end)
|
|
*
|
|
* The new perimeter should then be registered in the <mxStyleRegistry> as follows:
|
|
* (code)
|
|
* mxStyleRegistry.putValue('customPerimeter', mxPerimeter.CustomPerimeter);
|
|
* (end)
|
|
*
|
|
* The custom perimeter above can now be used in a specific vertex as follows:
|
|
*
|
|
* (code)
|
|
* model.setStyle(vertex, 'perimeter=customPerimeter');
|
|
* (end)
|
|
*
|
|
* Note that the key of the <mxStyleRegistry> entry for the function should
|
|
* be used in string values, unless <mxGraphView.allowEval> is true, in
|
|
* which case you can also use mxPerimeter.CustomPerimeter for the value in
|
|
* the cell style above.
|
|
*
|
|
* Or it can be used for all vertices in the graph as follows:
|
|
*
|
|
* (code)
|
|
* var style = graph.getStylesheet().getDefaultVertexStyle();
|
|
* style[mxConstants.STYLE_PERIMETER] = mxPerimeter.CustomPerimeter;
|
|
* (end)
|
|
*
|
|
* Note that the object can be used directly when programmatically setting
|
|
* the value, but the key in the <mxStyleRegistry> should be used when
|
|
* setting the value via a key, value pair in a cell style.
|
|
*
|
|
* The parameters are explained in <RectanglePerimeter>.
|
|
*
|
|
* Function: RectanglePerimeter
|
|
*
|
|
* Describes a rectangular perimeter for the given bounds.
|
|
*
|
|
* Parameters:
|
|
*
|
|
* bounds - <mxRectangle> that represents the absolute bounds of the
|
|
* vertex.
|
|
* vertex - <mxCellState> that represents the vertex.
|
|
* next - <mxPoint> that represents the nearest neighbour point on the
|
|
* given edge.
|
|
* orthogonal - Boolean that specifies if the orthogonal projection onto
|
|
* the perimeter should be returned. If this is false then the intersection
|
|
* of the perimeter and the line between the next and the center point is
|
|
* returned.
|
|
*/
|
|
RectanglePerimeter: function (bounds, vertex, next, orthogonal)
|
|
{
|
|
var cx = bounds.getCenterX();
|
|
var cy = bounds.getCenterY();
|
|
var dx = next.x - cx;
|
|
var dy = next.y - cy;
|
|
var alpha = Math.atan2(dy, dx);
|
|
var p = new mxPoint(0, 0);
|
|
var pi = Math.PI;
|
|
var pi2 = Math.PI/2;
|
|
var beta = pi2 - alpha;
|
|
var t = Math.atan2(bounds.height, bounds.width);
|
|
|
|
if (alpha < -pi + t || alpha > pi - t)
|
|
{
|
|
// Left edge
|
|
p.x = bounds.x;
|
|
p.y = cy - bounds.width * Math.tan(alpha) / 2;
|
|
}
|
|
else if (alpha < -t)
|
|
{
|
|
// Top Edge
|
|
p.y = bounds.y;
|
|
p.x = cx - bounds.height * Math.tan(beta) / 2;
|
|
}
|
|
else if (alpha < t)
|
|
{
|
|
// Right Edge
|
|
p.x = bounds.x + bounds.width;
|
|
p.y = cy + bounds.width * Math.tan(alpha) / 2;
|
|
}
|
|
else
|
|
{
|
|
// Bottom Edge
|
|
p.y = bounds.y + bounds.height;
|
|
p.x = cx + bounds.height * Math.tan(beta) / 2;
|
|
}
|
|
|
|
if (orthogonal)
|
|
{
|
|
if (next.x >= bounds.x &&
|
|
next.x <= bounds.x + bounds.width)
|
|
{
|
|
p.x = next.x;
|
|
}
|
|
else if (next.y >= bounds.y &&
|
|
next.y <= bounds.y + bounds.height)
|
|
{
|
|
p.y = next.y;
|
|
}
|
|
if (next.x < bounds.x)
|
|
{
|
|
p.x = bounds.x;
|
|
}
|
|
else if (next.x > bounds.x + bounds.width)
|
|
{
|
|
p.x = bounds.x + bounds.width;
|
|
}
|
|
if (next.y < bounds.y)
|
|
{
|
|
p.y = bounds.y;
|
|
}
|
|
else if (next.y > bounds.y + bounds.height)
|
|
{
|
|
p.y = bounds.y + bounds.height;
|
|
}
|
|
}
|
|
|
|
return p;
|
|
},
|
|
|
|
/**
|
|
* Function: EllipsePerimeter
|
|
*
|
|
* Describes an elliptic perimeter. See <RectanglePerimeter>
|
|
* for a description of the parameters.
|
|
*/
|
|
EllipsePerimeter: function (bounds, vertex, next, orthogonal)
|
|
{
|
|
var x = bounds.x;
|
|
var y = bounds.y;
|
|
var a = bounds.width / 2;
|
|
var b = bounds.height / 2;
|
|
var cx = x + a;
|
|
var cy = y + b;
|
|
var px = next.x;
|
|
var py = next.y;
|
|
|
|
// Calculates straight line equation through
|
|
// point and ellipse center y = d * x + h
|
|
var dx = parseInt(px - cx);
|
|
var dy = parseInt(py - cy);
|
|
|
|
if (dx == 0 && dy != 0)
|
|
{
|
|
return new mxPoint(cx, cy + b * dy / Math.abs(dy));
|
|
}
|
|
else if (dx == 0 && dy == 0)
|
|
{
|
|
return new mxPoint(px, py);
|
|
}
|
|
|
|
if (orthogonal)
|
|
{
|
|
if (py >= y && py <= y + bounds.height)
|
|
{
|
|
var ty = py - cy;
|
|
var tx = Math.sqrt(a*a*(1-(ty*ty)/(b*b))) || 0;
|
|
|
|
if (px <= x)
|
|
{
|
|
tx = -tx;
|
|
}
|
|
|
|
return new mxPoint(cx+tx, py);
|
|
}
|
|
|
|
if (px >= x && px <= x + bounds.width)
|
|
{
|
|
var tx = px - cx;
|
|
var ty = Math.sqrt(b*b*(1-(tx*tx)/(a*a))) || 0;
|
|
|
|
if (py <= y)
|
|
{
|
|
ty = -ty;
|
|
}
|
|
|
|
return new mxPoint(px, cy+ty);
|
|
}
|
|
}
|
|
|
|
// Calculates intersection
|
|
var d = dy / dx;
|
|
var h = cy - d * cx;
|
|
var e = a * a * d * d + b * b;
|
|
var f = -2 * cx * e;
|
|
var g = a * a * d * d * cx * cx +
|
|
b * b * cx * cx -
|
|
a * a * b * b;
|
|
var det = Math.sqrt(f * f - 4 * e * g);
|
|
|
|
// Two solutions (perimeter points)
|
|
var xout1 = (-f + det) / (2 * e);
|
|
var xout2 = (-f - det) / (2 * e);
|
|
var yout1 = d * xout1 + h;
|
|
var yout2 = d * xout2 + h;
|
|
var dist1 = Math.sqrt(Math.pow((xout1 - px), 2)
|
|
+ Math.pow((yout1 - py), 2));
|
|
var dist2 = Math.sqrt(Math.pow((xout2 - px), 2)
|
|
+ Math.pow((yout2 - py), 2));
|
|
|
|
// Correct solution
|
|
var xout = 0;
|
|
var yout = 0;
|
|
|
|
if (dist1 < dist2)
|
|
{
|
|
xout = xout1;
|
|
yout = yout1;
|
|
}
|
|
else
|
|
{
|
|
xout = xout2;
|
|
yout = yout2;
|
|
}
|
|
|
|
return new mxPoint(xout, yout);
|
|
},
|
|
|
|
/**
|
|
* Function: RhombusPerimeter
|
|
*
|
|
* Describes a rhombus (aka diamond) perimeter. See <RectanglePerimeter>
|
|
* for a description of the parameters.
|
|
*/
|
|
RhombusPerimeter: function (bounds, vertex, next, orthogonal)
|
|
{
|
|
var x = bounds.x;
|
|
var y = bounds.y;
|
|
var w = bounds.width;
|
|
var h = bounds.height;
|
|
|
|
var cx = x + w / 2;
|
|
var cy = y + h / 2;
|
|
|
|
var px = next.x;
|
|
var py = next.y;
|
|
|
|
// Special case for intersecting the diamond's corners
|
|
if (cx == px)
|
|
{
|
|
if (cy > py)
|
|
{
|
|
return new mxPoint(cx, y); // top
|
|
}
|
|
else
|
|
{
|
|
return new mxPoint(cx, y + h); // bottom
|
|
}
|
|
}
|
|
else if (cy == py)
|
|
{
|
|
if (cx > px)
|
|
{
|
|
return new mxPoint(x, cy); // left
|
|
}
|
|
else
|
|
{
|
|
return new mxPoint(x + w, cy); // right
|
|
}
|
|
}
|
|
|
|
var tx = cx;
|
|
var ty = cy;
|
|
|
|
if (orthogonal)
|
|
{
|
|
if (px >= x && px <= x + w)
|
|
{
|
|
tx = px;
|
|
}
|
|
else if (py >= y && py <= y + h)
|
|
{
|
|
ty = py;
|
|
}
|
|
}
|
|
|
|
// In which quadrant will the intersection be?
|
|
// set the slope and offset of the border line accordingly
|
|
if (px < cx)
|
|
{
|
|
if (py < cy)
|
|
{
|
|
return mxUtils.intersection(px, py, tx, ty, cx, y, x, cy);
|
|
}
|
|
else
|
|
{
|
|
return mxUtils.intersection(px, py, tx, ty, cx, y + h, x, cy);
|
|
}
|
|
}
|
|
else if (py < cy)
|
|
{
|
|
return mxUtils.intersection(px, py, tx, ty, cx, y, x + w, cy);
|
|
}
|
|
else
|
|
{
|
|
return mxUtils.intersection(px, py, tx, ty, cx, y + h, x + w, cy);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Function: TrianglePerimeter
|
|
*
|
|
* Describes a triangle perimeter. See <RectanglePerimeter>
|
|
* for a description of the parameters.
|
|
*/
|
|
TrianglePerimeter: function (bounds, vertex, next, orthogonal)
|
|
{
|
|
var direction = (vertex != null) ?
|
|
vertex.style[mxConstants.STYLE_DIRECTION] : null;
|
|
var vertical = direction == mxConstants.DIRECTION_NORTH ||
|
|
direction == mxConstants.DIRECTION_SOUTH;
|
|
|
|
var x = bounds.x;
|
|
var y = bounds.y;
|
|
var w = bounds.width;
|
|
var h = bounds.height;
|
|
|
|
var cx = x + w / 2;
|
|
var cy = y + h / 2;
|
|
|
|
var start = new mxPoint(x, y);
|
|
var corner = new mxPoint(x + w, cy);
|
|
var end = new mxPoint(x, y + h);
|
|
|
|
if (direction == mxConstants.DIRECTION_NORTH)
|
|
{
|
|
start = end;
|
|
corner = new mxPoint(cx, y);
|
|
end = new mxPoint(x + w, y + h);
|
|
}
|
|
else if (direction == mxConstants.DIRECTION_SOUTH)
|
|
{
|
|
corner = new mxPoint(cx, y + h);
|
|
end = new mxPoint(x + w, y);
|
|
}
|
|
else if (direction == mxConstants.DIRECTION_WEST)
|
|
{
|
|
start = new mxPoint(x + w, y);
|
|
corner = new mxPoint(x, cy);
|
|
end = new mxPoint(x + w, y + h);
|
|
}
|
|
|
|
var dx = next.x - cx;
|
|
var dy = next.y - cy;
|
|
|
|
var alpha = (vertical) ? Math.atan2(dx, dy) : Math.atan2(dy, dx);
|
|
var t = (vertical) ? Math.atan2(w, h) : Math.atan2(h, w);
|
|
|
|
var base = false;
|
|
|
|
if (direction == mxConstants.DIRECTION_NORTH ||
|
|
direction == mxConstants.DIRECTION_WEST)
|
|
{
|
|
base = alpha > -t && alpha < t;
|
|
}
|
|
else
|
|
{
|
|
base = alpha < -Math.PI + t || alpha > Math.PI - t;
|
|
}
|
|
|
|
var result = null;
|
|
|
|
if (base)
|
|
{
|
|
if (orthogonal && ((vertical && next.x >= start.x && next.x <= end.x) ||
|
|
(!vertical && next.y >= start.y && next.y <= end.y)))
|
|
{
|
|
if (vertical)
|
|
{
|
|
result = new mxPoint(next.x, start.y);
|
|
}
|
|
else
|
|
{
|
|
result = new mxPoint(start.x, next.y);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (direction == mxConstants.DIRECTION_NORTH)
|
|
{
|
|
result = new mxPoint(x + w / 2 + h * Math.tan(alpha) / 2,
|
|
y + h);
|
|
}
|
|
else if (direction == mxConstants.DIRECTION_SOUTH)
|
|
{
|
|
result = new mxPoint(x + w / 2 - h * Math.tan(alpha) / 2,
|
|
y);
|
|
}
|
|
else if (direction == mxConstants.DIRECTION_WEST)
|
|
{
|
|
result = new mxPoint(x + w, y + h / 2 +
|
|
w * Math.tan(alpha) / 2);
|
|
}
|
|
else
|
|
{
|
|
result = new mxPoint(x, y + h / 2 -
|
|
w * Math.tan(alpha) / 2);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (orthogonal)
|
|
{
|
|
var pt = new mxPoint(cx, cy);
|
|
|
|
if (next.y >= y && next.y <= y + h)
|
|
{
|
|
pt.x = (vertical) ? cx : (
|
|
(direction == mxConstants.DIRECTION_WEST) ?
|
|
x + w : x);
|
|
pt.y = next.y;
|
|
}
|
|
else if (next.x >= x && next.x <= x + w)
|
|
{
|
|
pt.x = next.x;
|
|
pt.y = (!vertical) ? cy : (
|
|
(direction == mxConstants.DIRECTION_NORTH) ?
|
|
y + h : y);
|
|
}
|
|
|
|
// Compute angle
|
|
dx = next.x - pt.x;
|
|
dy = next.y - pt.y;
|
|
|
|
cx = pt.x;
|
|
cy = pt.y;
|
|
}
|
|
|
|
if ((vertical && next.x <= x + w / 2) ||
|
|
(!vertical && next.y <= y + h / 2))
|
|
{
|
|
result = mxUtils.intersection(next.x, next.y, cx, cy,
|
|
start.x, start.y, corner.x, corner.y);
|
|
}
|
|
else
|
|
{
|
|
result = mxUtils.intersection(next.x, next.y, cx, cy,
|
|
corner.x, corner.y, end.x, end.y);
|
|
}
|
|
}
|
|
|
|
if (result == null)
|
|
{
|
|
result = new mxPoint(cx, cy);
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Function: HexagonPerimeter
|
|
*
|
|
* Describes a hexagon perimeter. See <RectanglePerimeter>
|
|
* for a description of the parameters.
|
|
*/
|
|
HexagonPerimeter: function (bounds, vertex, next, orthogonal)
|
|
{
|
|
var x = bounds.x;
|
|
var y = bounds.y;
|
|
var w = bounds.width;
|
|
var h = bounds.height;
|
|
|
|
var cx = bounds.getCenterX();
|
|
var cy = bounds.getCenterY();
|
|
var px = next.x;
|
|
var py = next.y;
|
|
var dx = px - cx;
|
|
var dy = py - cy;
|
|
var alpha = -Math.atan2(dy, dx);
|
|
var pi = Math.PI;
|
|
var pi2 = Math.PI / 2;
|
|
|
|
var result = new mxPoint(cx, cy);
|
|
|
|
var direction = (vertex != null) ? mxUtils.getValue(
|
|
vertex.style, mxConstants.STYLE_DIRECTION,
|
|
mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
|
|
var vertical = direction == mxConstants.DIRECTION_NORTH
|
|
|| direction == mxConstants.DIRECTION_SOUTH;
|
|
var a = new mxPoint();
|
|
var b = new mxPoint();
|
|
|
|
//Only consider corrects quadrants for the orthogonal case.
|
|
if ((px < x) && (py < y) || (px < x) && (py > y + h)
|
|
|| (px > x + w) && (py < y) || (px > x + w) && (py > y + h))
|
|
{
|
|
orthogonal = false;
|
|
}
|
|
|
|
if (orthogonal)
|
|
{
|
|
if (vertical)
|
|
{
|
|
//Special cases where intersects with hexagon corners
|
|
if (px == cx)
|
|
{
|
|
if (py <= y)
|
|
{
|
|
return new mxPoint(cx, y);
|
|
}
|
|
else if (py >= y + h)
|
|
{
|
|
return new mxPoint(cx, y + h);
|
|
}
|
|
}
|
|
else if (px < x)
|
|
{
|
|
if (py == y + h / 4)
|
|
{
|
|
return new mxPoint(x, y + h / 4);
|
|
}
|
|
else if (py == y + 3 * h / 4)
|
|
{
|
|
return new mxPoint(x, y + 3 * h / 4);
|
|
}
|
|
}
|
|
else if (px > x + w)
|
|
{
|
|
if (py == y + h / 4)
|
|
{
|
|
return new mxPoint(x + w, y + h / 4);
|
|
}
|
|
else if (py == y + 3 * h / 4)
|
|
{
|
|
return new mxPoint(x + w, y + 3 * h / 4);
|
|
}
|
|
}
|
|
else if (px == x)
|
|
{
|
|
if (py < cy)
|
|
{
|
|
return new mxPoint(x, y + h / 4);
|
|
}
|
|
else if (py > cy)
|
|
{
|
|
return new mxPoint(x, y + 3 * h / 4);
|
|
}
|
|
}
|
|
else if (px == x + w)
|
|
{
|
|
if (py < cy)
|
|
{
|
|
return new mxPoint(x + w, y + h / 4);
|
|
}
|
|
else if (py > cy)
|
|
{
|
|
return new mxPoint(x + w, y + 3 * h / 4);
|
|
}
|
|
}
|
|
if (py == y)
|
|
{
|
|
return new mxPoint(cx, y);
|
|
}
|
|
else if (py == y + h)
|
|
{
|
|
return new mxPoint(cx, y + h);
|
|
}
|
|
|
|
if (px < cx)
|
|
{
|
|
if ((py > y + h / 4) && (py < y + 3 * h / 4))
|
|
{
|
|
a = new mxPoint(x, y);
|
|
b = new mxPoint(x, y + h);
|
|
}
|
|
else if (py < y + h / 4)
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
b = new mxPoint(x + w, y - Math.floor(0.25 * h));
|
|
}
|
|
else if (py > y + 3 * h / 4)
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
b = new mxPoint(x + w, y + Math.floor(1.25 * h));
|
|
}
|
|
}
|
|
else if (px > cx)
|
|
{
|
|
if ((py > y + h / 4) && (py < y + 3 * h / 4))
|
|
{
|
|
a = new mxPoint(x + w, y);
|
|
b = new mxPoint(x + w, y + h);
|
|
}
|
|
else if (py < y + h / 4)
|
|
{
|
|
a = new mxPoint(x, y - Math.floor(0.25 * h));
|
|
b = new mxPoint(x + Math.floor(1.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
}
|
|
else if (py > y + 3 * h / 4)
|
|
{
|
|
a = new mxPoint(x + Math.floor(1.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
b = new mxPoint(x, y + Math.floor(1.25 * h));
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//Special cases where intersects with hexagon corners
|
|
if (py == cy)
|
|
{
|
|
if (px <= x)
|
|
{
|
|
return new mxPoint(x, y + h / 2);
|
|
}
|
|
else if (px >= x + w)
|
|
{
|
|
return new mxPoint(x + w, y + h / 2);
|
|
}
|
|
}
|
|
else if (py < y)
|
|
{
|
|
if (px == x + w / 4)
|
|
{
|
|
return new mxPoint(x + w / 4, y);
|
|
}
|
|
else if (px == x + 3 * w / 4)
|
|
{
|
|
return new mxPoint(x + 3 * w / 4, y);
|
|
}
|
|
}
|
|
else if (py > y + h)
|
|
{
|
|
if (px == x + w / 4)
|
|
{
|
|
return new mxPoint(x + w / 4, y + h);
|
|
}
|
|
else if (px == x + 3 * w / 4)
|
|
{
|
|
return new mxPoint(x + 3 * w / 4, y + h);
|
|
}
|
|
}
|
|
else if (py == y)
|
|
{
|
|
if (px < cx)
|
|
{
|
|
return new mxPoint(x + w / 4, y);
|
|
}
|
|
else if (px > cx)
|
|
{
|
|
return new mxPoint(x + 3 * w / 4, y);
|
|
}
|
|
}
|
|
else if (py == y + h)
|
|
{
|
|
if (px < cx)
|
|
{
|
|
return new mxPoint(x + w / 4, y + h);
|
|
}
|
|
else if (py > cy)
|
|
{
|
|
return new mxPoint(x + 3 * w / 4, y + h);
|
|
}
|
|
}
|
|
if (px == x)
|
|
{
|
|
return new mxPoint(x, cy);
|
|
}
|
|
else if (px == x + w)
|
|
{
|
|
return new mxPoint(x + w, cy);
|
|
}
|
|
|
|
if (py < cy)
|
|
{
|
|
if ((px > x + w / 4) && (px < x + 3 * w / 4))
|
|
{
|
|
a = new mxPoint(x, y);
|
|
b = new mxPoint(x + w, y);
|
|
}
|
|
else if (px < x + w / 4)
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.25 * w), y + h);
|
|
b = new mxPoint(x + Math.floor(0.5 * w), y
|
|
- Math.floor(0.5 * h));
|
|
}
|
|
else if (px > x + 3 * w / 4)
|
|
{
|
|
a = new mxPoint(x + Math.floor(0.5 * w), y
|
|
- Math.floor(0.5 * h));
|
|
b = new mxPoint(x + Math.floor(1.25 * w), y + h);
|
|
}
|
|
}
|
|
else if (py > cy)
|
|
{
|
|
if ((px > x + w / 4) && (px < x + 3 * w / 4))
|
|
{
|
|
a = new mxPoint(x, y + h);
|
|
b = new mxPoint(x + w, y + h);
|
|
}
|
|
else if (px < x + w / 4)
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.25 * w), y);
|
|
b = new mxPoint(x + Math.floor(0.5 * w), y
|
|
+ Math.floor(1.5 * h));
|
|
}
|
|
else if (px > x + 3 * w / 4)
|
|
{
|
|
a = new mxPoint(x + Math.floor(0.5 * w), y
|
|
+ Math.floor(1.5 * h));
|
|
b = new mxPoint(x + Math.floor(1.25 * w), y);
|
|
}
|
|
}
|
|
}
|
|
|
|
var tx = cx;
|
|
var ty = cy;
|
|
|
|
if (px >= x && px <= x + w)
|
|
{
|
|
tx = px;
|
|
|
|
if (py < cy)
|
|
{
|
|
ty = y + h;
|
|
}
|
|
else
|
|
{
|
|
ty = y;
|
|
}
|
|
}
|
|
else if (py >= y && py <= y + h)
|
|
{
|
|
ty = py;
|
|
|
|
if (px < cx)
|
|
{
|
|
tx = x + w;
|
|
}
|
|
else
|
|
{
|
|
tx = x;
|
|
}
|
|
}
|
|
|
|
result = mxUtils.intersection(tx, ty, next.x, next.y, a.x, a.y, b.x, b.y);
|
|
}
|
|
else
|
|
{
|
|
if (vertical)
|
|
{
|
|
var beta = Math.atan2(h / 4, w / 2);
|
|
|
|
//Special cases where intersects with hexagon corners
|
|
if (alpha == beta)
|
|
{
|
|
return new mxPoint(x + w, y + Math.floor(0.25 * h));
|
|
}
|
|
else if (alpha == pi2)
|
|
{
|
|
return new mxPoint(x + Math.floor(0.5 * w), y);
|
|
}
|
|
else if (alpha == (pi - beta))
|
|
{
|
|
return new mxPoint(x, y + Math.floor(0.25 * h));
|
|
}
|
|
else if (alpha == -beta)
|
|
{
|
|
return new mxPoint(x + w, y + Math.floor(0.75 * h));
|
|
}
|
|
else if (alpha == (-pi2))
|
|
{
|
|
return new mxPoint(x + Math.floor(0.5 * w), y + h);
|
|
}
|
|
else if (alpha == (-pi + beta))
|
|
{
|
|
return new mxPoint(x, y + Math.floor(0.75 * h));
|
|
}
|
|
|
|
if ((alpha < beta) && (alpha > -beta))
|
|
{
|
|
a = new mxPoint(x + w, y);
|
|
b = new mxPoint(x + w, y + h);
|
|
}
|
|
else if ((alpha > beta) && (alpha < pi2))
|
|
{
|
|
a = new mxPoint(x, y - Math.floor(0.25 * h));
|
|
b = new mxPoint(x + Math.floor(1.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
}
|
|
else if ((alpha > pi2) && (alpha < (pi - beta)))
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
b = new mxPoint(x + w, y - Math.floor(0.25 * h));
|
|
}
|
|
else if (((alpha > (pi - beta)) && (alpha <= pi))
|
|
|| ((alpha < (-pi + beta)) && (alpha >= -pi)))
|
|
{
|
|
a = new mxPoint(x, y);
|
|
b = new mxPoint(x, y + h);
|
|
}
|
|
else if ((alpha < -beta) && (alpha > -pi2))
|
|
{
|
|
a = new mxPoint(x + Math.floor(1.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
b = new mxPoint(x, y + Math.floor(1.25 * h));
|
|
}
|
|
else if ((alpha < -pi2) && (alpha > (-pi + beta)))
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.5 * w), y
|
|
+ Math.floor(0.5 * h));
|
|
b = new mxPoint(x + w, y + Math.floor(1.25 * h));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var beta = Math.atan2(h / 2, w / 4);
|
|
|
|
//Special cases where intersects with hexagon corners
|
|
if (alpha == beta)
|
|
{
|
|
return new mxPoint(x + Math.floor(0.75 * w), y);
|
|
}
|
|
else if (alpha == (pi - beta))
|
|
{
|
|
return new mxPoint(x + Math.floor(0.25 * w), y);
|
|
}
|
|
else if ((alpha == pi) || (alpha == -pi))
|
|
{
|
|
return new mxPoint(x, y + Math.floor(0.5 * h));
|
|
}
|
|
else if (alpha == 0)
|
|
{
|
|
return new mxPoint(x + w, y + Math.floor(0.5 * h));
|
|
}
|
|
else if (alpha == -beta)
|
|
{
|
|
return new mxPoint(x + Math.floor(0.75 * w), y + h);
|
|
}
|
|
else if (alpha == (-pi + beta))
|
|
{
|
|
return new mxPoint(x + Math.floor(0.25 * w), y + h);
|
|
}
|
|
|
|
if ((alpha > 0) && (alpha < beta))
|
|
{
|
|
a = new mxPoint(x + Math.floor(0.5 * w), y
|
|
- Math.floor(0.5 * h));
|
|
b = new mxPoint(x + Math.floor(1.25 * w), y + h);
|
|
}
|
|
else if ((alpha > beta) && (alpha < (pi - beta)))
|
|
{
|
|
a = new mxPoint(x, y);
|
|
b = new mxPoint(x + w, y);
|
|
}
|
|
else if ((alpha > (pi - beta)) && (alpha < pi))
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.25 * w), y + h);
|
|
b = new mxPoint(x + Math.floor(0.5 * w), y
|
|
- Math.floor(0.5 * h));
|
|
}
|
|
else if ((alpha < 0) && (alpha > -beta))
|
|
{
|
|
a = new mxPoint(x + Math.floor(0.5 * w), y
|
|
+ Math.floor(1.5 * h));
|
|
b = new mxPoint(x + Math.floor(1.25 * w), y);
|
|
}
|
|
else if ((alpha < -beta) && (alpha > (-pi + beta)))
|
|
{
|
|
a = new mxPoint(x, y + h);
|
|
b = new mxPoint(x + w, y + h);
|
|
}
|
|
else if ((alpha < (-pi + beta)) && (alpha > -pi))
|
|
{
|
|
a = new mxPoint(x - Math.floor(0.25 * w), y);
|
|
b = new mxPoint(x + Math.floor(0.5 * w), y
|
|
+ Math.floor(1.5 * h));
|
|
}
|
|
}
|
|
|
|
result = mxUtils.intersection(cx, cy, next.x, next.y, a.x, a.y, b.x, b.y);
|
|
}
|
|
|
|
if (result == null)
|
|
{
|
|
return new mxPoint(cx, cy);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
};
|