/**
 * Copyright (c) 2006-2015, JGraph Holdings Ltd
 * Copyright (c) 2006-2015, draw.io AG
 */
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;
	}
};
