void ShiftNodes()
{
if (type != PrimitiveType.MinimalCycle)
{
return;
}
Dictionary <string, Vector3> newNodePositionDict = new Dictionary <string, Vector3>();
for (int i = 0; i < nodes.Count; i++)
{
position += nodes[i].Position;
if (nodes[i].adjacents.Count != 2)
{
continue;
}
Node prevNode = null;
Node nextNode = null;
if (i == 0)
{
prevNode = nodes[nodes.Count - 1];
nextNode = nodes[i + 1];
}
else if (i == nodes.Count - 1)
{
prevNode = nodes[i - 1];
nextNode = nodes[0];
}
else
{
prevNode = nodes[i - 1];
nextNode = nodes[i + 1];
}
Vector3 dirToPrev = (prevNode.Position - nodes[i].Position).normalized;
Vector3 dirToNext = (nextNode.Position - nodes[i].Position).normalized;
Edge prevEdge = EdgeGraphUtility.FindEdgeByNodes(nodes[i], prevNode, edges);
Edge nextEdge = EdgeGraphUtility.FindEdgeByNodes(nodes[i], nextNode, edges);
Node prevEdgeOtherNode = prevEdge.Node1 == nodes[i].ID ? Node.GetNode(nodes, prevEdge.Node2) : Node.GetNode(nodes, prevEdge.Node1);
Node nextEdgeOtherNode = nextEdge.Node1 == nodes[i].ID ? Node.GetNode(nodes, nextEdge.Node2) : Node.GetNode(nodes, nextEdge.Node1);
if (prevEdgeOtherNode == null || nextEdgeOtherNode == null)
{
continue;
}
Vector3 prevLeftNormal = Edge.GetLeftPerpendicular(prevEdgeOtherNode.Position, nodes[i].Position);
Vector3 nextLeftNormal = Edge.GetLeftPerpendicular(nodes[i].Position, nextEdgeOtherNode.Position);
Vector3 newNodePos = nodes[i].Position;
// In case the next and edge create a 180 degree angle, just shift this node towards the left normal
if (Mathf.Approximately(Vector3.Dot(dirToNext, dirToPrev), -1f))
{
float avgEdgeWidth = (prevEdge.Width + nextEdge.Width) / 2f;
newNodePos = nodes[i].Position + prevLeftNormal * avgEdgeWidth / 2f;
}
else
{
// Shifted edges, streched a bit to ensure the intersection point
Vector3 prevEdgeNormalPoint = EdgeGraphUtility.GetEdgePosition(prevEdge.ID, ref nodes, ref edges) + prevLeftNormal * (prevEdge.Width / 2f);
float prevEdgeLength = Vector3.Distance(nodes[i].Position, prevEdgeOtherNode.Position);
Vector3 prevEdgeFar = prevEdgeNormalPoint + dirToPrev * prevEdgeLength * 2f;
Vector3 prevEdgeNear = prevEdgeNormalPoint - dirToPrev * prevEdgeLength * 2f;
Vector3 nextEdgeNormalPoint = EdgeGraphUtility.GetEdgePosition(nextEdge.ID, ref nodes, ref edges) + nextLeftNormal * (nextEdge.Width / 2f);
float nextEdgeLength = Vector3.Distance(nodes[i].Position, nextEdgeOtherNode.Position);
Vector3 nextEdgeFar = nextEdgeNormalPoint + dirToNext * nextEdgeLength * 2f;
Vector3 nextEdgeNear = nextEdgeNormalPoint - dirToNext * nextEdgeLength * 2f;
// Get intersect point of the shifted edges
Vector3 intersectPoint = nodes[i].Position;
Vector3 intersectPointXZ;
if (UtilityTools.MathHelper.AreIntersecting(out intersectPointXZ, prevEdgeFar, prevEdgeNear, nextEdgeFar, nextEdgeNear) == 1)
{
intersectPoint = new Vector3(intersectPointXZ.x, nodes[i].Position.y, intersectPointXZ.y);
}
//Vector3 nodeToNew = (intersectPoint - nodes[i].Position).normalized;
//Vector3 prevToNew = (intersectPoint - prevEdgeOtherNode.Position).normalized;
//Vector3 nextToNew = (intersectPoint - nextEdgeOtherNode.Position).normalized;
newNodePos = intersectPoint;
}
newNodePositionDict.Add(nodes[i].ID, newNodePos);
}
position /= nodes.Count;
//Set shifted positions
for (int i = 0; i < nodes.Count; i++)
{
if (newNodePositionDict.ContainsKey(nodes[i].ID))
{
nodes[i].Position = newNodePositionDict[nodes[i].ID];
}
}
}