/// <summary> /// Transform door line according to a given transformation. /// </summary> /// <param name="doorLine"></param> /// <param name="transformation"></param> /// <returns></returns> public static IDoorLine TransformDoorLine(IDoorLine doorLine, Transformation transformation) { var doorPosition = doorLine.Line; if (doorPosition.GetDirection() == OrthogonalLine.Direction.Undefined) { throw new InvalidOperationException("Cannot fix door direction when original direction is undefined"); } switch (transformation) { case Transformation.Identity: return(doorLine); case Transformation.Rotate90: return(new DoorLine(doorPosition.Rotate(90), doorLine.Length)); case Transformation.Rotate180: return(new DoorLine(doorPosition.Rotate(180), doorLine.Length)); case Transformation.Rotate270: return(new DoorLine(doorPosition.Rotate(270), doorLine.Length)); } // Other transformations need to switch door directions var firstStartPoint = doorPosition.From.Transform(transformation); var lastStartPoint = doorPosition.To.Transform(transformation); var length = doorLine.Length; var transformedDirection = TransformDirection(doorPosition.GetDirection(), transformation); var transformedLine = new OrthogonalLine(firstStartPoint, lastStartPoint, transformedDirection); var lastEndPoint = lastStartPoint + length * transformedLine.GetDirectionVector(); var newDirection = OrthogonalLine.GetOppositeDirection(transformedDirection); var newDoorPosition = new OrthogonalLine(lastEndPoint, lastEndPoint + transformedLine.Length * transformedLine.SwitchOrientation().GetDirectionVector(), newDirection); if (newDoorPosition.Length != doorPosition.Length) { throw new InvalidOperationException(); } return(new DoorLine(newDoorPosition, doorLine.Length)); }
private static OrthogonalLine.Direction TransformDirection(OrthogonalLine.Direction originalDirection, Transformation transformation) { if (originalDirection == OrthogonalLine.Direction.Undefined) { throw new InvalidOperationException("Cannot transform direction when original direction is undefined"); } switch (transformation) { case Transformation.MirrorX: if (IsHorizontal(originalDirection)) { return(originalDirection); } return(OrthogonalLine.GetOppositeDirection(originalDirection)); case Transformation.MirrorY: if (IsHorizontal(originalDirection)) { return(OrthogonalLine.GetOppositeDirection(originalDirection)); } return(originalDirection); case Transformation.Diagonal13: switch (originalDirection) { case OrthogonalLine.Direction.Top: return(OrthogonalLine.Direction.Right); case OrthogonalLine.Direction.Right: return(OrthogonalLine.Direction.Top); case OrthogonalLine.Direction.Bottom: return(OrthogonalLine.Direction.Left); case OrthogonalLine.Direction.Left: return(OrthogonalLine.Direction.Bottom); default: throw new ArgumentException(); } case Transformation.Diagonal24: switch (originalDirection) { case OrthogonalLine.Direction.Top: return(OrthogonalLine.Direction.Left); case OrthogonalLine.Direction.Right: return(OrthogonalLine.Direction.Bottom); case OrthogonalLine.Direction.Bottom: return(OrthogonalLine.Direction.Right); case OrthogonalLine.Direction.Left: return(OrthogonalLine.Direction.Top); default: throw new ArgumentException(); } } throw new ArgumentException(); }
private ConfigurationSpace GetConfigurationSpace(GridPolygon polygon, List <IDoorLine> doorLines, GridPolygon fixedCenter, List <IDoorLine> doorLinesFixed, List <int> offsets = null) { if (offsets != null && offsets.Count == 0) { throw new ArgumentException("There must be at least one offset if they are set", nameof(offsets)); } var configurationSpaceLines = new List <OrthogonalLine>(); var reverseDoor = new List <Tuple <OrthogonalLine, DoorLine> >(); doorLines = DoorUtils.MergeDoorLines(doorLines); doorLinesFixed = DoorUtils.MergeDoorLines(doorLinesFixed); // One list for every direction var lines = new List <IDoorLine> [4]; // Init array for (var i = 0; i < lines.Length; i++) { lines[i] = new List <IDoorLine>(); } // Populate lists with lines foreach (var line in doorLinesFixed) { lines[(int)line.Line.GetDirection()].Add(line); } foreach (var doorLine in doorLines) { var line = doorLine.Line; var oppositeDirection = OrthogonalLine.GetOppositeDirection(line.GetDirection()); var rotation = line.ComputeRotation(); var rotatedLine = line.Rotate(rotation); var correspondingLines = lines[(int)oppositeDirection].Where(x => x.Length == doorLine.Length).Select(x => new DoorLine(x.Line.Rotate(rotation), x.Length)); foreach (var cDoorLine in correspondingLines) { var cline = cDoorLine.Line; var y = cline.From.Y - rotatedLine.From.Y; var from = new IntVector2(cline.From.X - rotatedLine.To.X + (rotatedLine.Length - doorLine.Length), y); var to = new IntVector2(cline.To.X - rotatedLine.From.X - (rotatedLine.Length + doorLine.Length), y); if (from.X < to.X) { continue; } if (offsets == null) { var resultLine = new OrthogonalLine(from, to, OrthogonalLine.Direction.Left).Rotate(-rotation); reverseDoor.Add(Tuple.Create(resultLine, new DoorLine(cDoorLine.Line.Rotate(-rotation), cDoorLine.Length))); configurationSpaceLines.Add(resultLine); } else { foreach (var offset in offsets) { var offsetVector = new IntVector2(0, offset); var resultLine = new OrthogonalLine(from - offsetVector, to - offsetVector, OrthogonalLine.Direction.Left).Rotate(-rotation); reverseDoor.Add(Tuple.Create(resultLine, new DoorLine(cDoorLine.Line.Rotate(-rotation), cDoorLine.Length))); configurationSpaceLines.Add(resultLine); } } } } // Remove all positions when the two polygons overlap configurationSpaceLines = RemoveOverlapping(polygon, fixedCenter, configurationSpaceLines); // Remove all non-unique positions configurationSpaceLines = RemoveIntersections(configurationSpaceLines); return(new ConfigurationSpace() { Lines = configurationSpaceLines, ReverseDoors = reverseDoor }); }