/// <summary> /// When called, the new badge shape is already created /// </summary> void GetBadgeSmartLocation(int ownerId, out double x, out double y) { IServerVdShape[] badges = _doc.GetShapes().Where(sh => sh.ShapeCode() == VdShapeType.Badge).ToArray(); int[] ownerIds = badges.Select(b => b.InitialOwner()).Distinct().ToArray(); IServerVdShape[] ownerBadges = badges.Where(b => b.InitialOwner() == ownerId).ToArray(); double clusterLeft; double clusterTop; const double TopMargin = 80; const double LeftMargin = 140; const double RightMargin = 140; const double BottomMargin = 80; if (ownerBadges.Length <= 1) { //this is the first owner's cluster switch (ownerIds.Length) { case 1: clusterLeft = BoardWidth / 2; clusterTop = BoardHeight / 2; break; case 2: clusterLeft = LeftMargin; clusterTop = 0.5 * BoardHeight; break; case 3: clusterLeft = BoardWidth - RightMargin; clusterTop = 0.5 * BoardHeight; break; case 4: //top left clusterLeft = LeftMargin; clusterTop = TopMargin; break; case 5: //top right clusterLeft = BoardWidth - RightMargin; clusterTop = TopMargin; break; case 6: //bottom left clusterLeft = LeftMargin; clusterTop = BoardHeight - BottomMargin; break; case 7: //bottom right clusterLeft = BoardWidth - RightMargin; clusterTop = BoardHeight - BottomMargin; break; default: var rnd = new Random(); clusterLeft = BoardWidth * rnd.NextDouble(); clusterTop = BoardHeight * rnd.NextDouble(); break; } } else { //the owner has previous badges, //extract the firt badge that marks top left of its cluster clusterLeft = ownerBadges[0].GetState().doubles[0]; clusterTop = ownerBadges[0].GetState().doubles[1]; } int indexOfTheBadge = ownerBadges.Length - 1; const int maxCols = 3; int row = indexOfTheBadge / maxCols; int col = indexOfTheBadge - row * maxCols; var rnd2 = new Random(); double xRnd, yRnd; xRnd = clusterLeft + col * (BadgeShapeWidth + rnd2.NextDouble() * BadgeHGap); yRnd = clusterTop + row * (BadgeShapeHeight + rnd2.NextDouble() * BadgeVGap); x = xRnd; y = yRnd; }