/// <summary> /// this function tries to sort lines, but it can throw exception when it fails /// </summary> public void SortLines() { List <_Line> orderedLines = new List <_Line>(); int actualIndex = 0;//the basis of sorting is to loop and keep this actualindex int boundCount = Lines.Count; int nullLinesCount = 0; for (int i = 0; i < boundCount; i++) { _Line loopLine = Lines[actualIndex]; if (loopLine.StartPoint.Equals(loopLine.EndPoint)) { nullLinesCount++; continue; //we remove null lines this way } orderedLines.Add(loopLine); actualIndex = 0; for (var j = 0; j < boundCount; j++) { _Line innerLoopLine = Lines[j]; if (orderedLines.Contains(innerLoopLine)) { actualIndex++; //so skip this line continue; } //from these next statments, only one can be true if (Equals(innerLoopLine.StartPoint, loopLine.StartPoint) && !Equals(innerLoopLine.EndPoint, loopLine.EndPoint)) { break; } if (Equals(innerLoopLine.StartPoint, loopLine.EndPoint) && !Equals(innerLoopLine.EndPoint, loopLine.StartPoint)) { break; } if (Equals(innerLoopLine.EndPoint, loopLine.EndPoint) && !Equals(innerLoopLine.StartPoint, loopLine.StartPoint)) { break; } if (Equals(innerLoopLine.EndPoint, loopLine.StartPoint) && !Equals(innerLoopLine.StartPoint, loopLine.EndPoint)) { break; } actualIndex++; } } _Point p1 = orderedLines.First().ConnectsPoint(orderedLines.Last()); //this is where the first and last line joins _Point p2 = orderedLines.ElementAt(1).ConnectsPoint(orderedLines.ElementAt(0)); //this is where the first and second line joins _Point p3 = orderedLines.Last().ConnectsPoint(orderedLines.ElementAt(orderedLines.Count - 2)); //this is where the last and the line before last joins //so this is the point where the first and second line connect //so p0 is where it all started. the last line should have p0 _Point p0 = orderedLines.First().StartPoint.Equals(p2) ? orderedLines.First().EndPoint : orderedLines.First().StartPoint; //to get full circle _Point p4 = orderedLines.Last().StartPoint.Equals(p3) ? orderedLines.Last().EndPoint : orderedLines.Last().StartPoint; bool isGoodOrdering = p1 != null && p1.Equals(p0) && p1.Equals(p4); bool isGoodCount = (orderedLines.Count + nullLinesCount) == Lines.Count; if (!isGoodOrdering) { throw new Exception("first and last line does not connect"); } if (!isGoodCount) { throw new Exception("not enough lines"); } Lines = orderedLines; }
private List <_Room> roomsContainingTheLineToMove = new List <_Room>(); //these rooms might need to change public void MoveLine(int distance, _Line lineToMove) { //if (lineToMove.length < 11) //return; roomsContainingTheLineToMove.Clear(); roomsTouchingStartPoint.Clear(); roomsTouchingEndPoint.Clear(); roomsTouchingStartPointOnlyAndHaveNoParallelLines.Clear(); roomsTouchingEndPointOnlyAndHaveNoParalellLines.Clear(); _Line movedLine = lineToMove.DeepCopy(); //first we copy the line we need to move movedLine.Name = $"Moved_in_step:{moveStepsCount}"; //this is for debugging _Point moveVector = movedLine.GetNV(true) * distance; //we scale it up movedLine.Move(moveVector); //so we moved the copy (why not the actual?) _Line l1 = new _Line(lineToMove.StartPoint, lineToMove.StartPoint.Move(moveVector)); _Line l2 = new _Line(lineToMove.EndPoint, lineToMove.EndPoint.Move(moveVector)); l1.Name = $"New_Start_Line_{moveStepsCount}"; l2.Name = $"New_End_Line_{moveStepsCount}"; fillRelatedRoomListInfomration(lineToMove, ref l1, ref l2); List <_Line> linesToRemove = new List <_Line>(); //this is the big function foreach (_Room room in roomsContainingTheLineToMove) { bool shouldBeTrue = room.CanGetBoundarySorted(); int linetoMoveOriginal = room.Lines.FindIndex(a => a.Equals(lineToMove)); if (linetoMoveOriginal == -1) { linetoMoveOriginal = 0; } room.Lines.Remove(lineToMove); int linesCount = room.Lines.Count; for (var index = 0; index < linesCount; index++) { _Line lineInLoop = room.Lines[index]; _Point loopAndToMoveCommonPoint = lineInLoop.ConnectsPoint(lineToMove); if (loopAndToMoveCommonPoint != null && loopAndToMoveCommonPoint.Equals(lineToMove.StartPoint)) //there is common point with startpoint, so this line touched the old startpoint { bool areweMovingOnLoopLine = IsOnLineButNotEndPoint(l1.EndPoint, lineInLoop); //if there is a touching room, we need to keep the point. of course, might not in this room. if (!roomsTouchingStartPoint.Any()) { _Point loopNormal = lineInLoop.GetNV(true); //we need to either move it, if it is parallel, or keep it if it is merőleges _Point moveNormal = lineToMove.GetNV(true); //THE LINE SHOULD MOVE - BOTH DIRECTIONS - MOVE P WITH MOVEVECTOR bool NOTparallel = AreNotParralel(loopNormal, moveNormal); if (lineInLoop.StartPoint.Equals(loopAndToMoveCommonPoint) && (NOTparallel)) { lineInLoop.StartPoint = lineInLoop.StartPoint.Move(moveVector); } if (lineInLoop.EndPoint.Equals(loopAndToMoveCommonPoint) && (NOTparallel)) { lineInLoop.EndPoint = lineInLoop.EndPoint.Move(moveVector); } if (lineInLoop.StartPoint.Equals(lineInLoop.EndPoint)) { linesToRemove.Add(lineInLoop); } if ((lineInLoop.StartPoint.Equals(loopAndToMoveCommonPoint) || lineInLoop.EndPoint.Equals(loopAndToMoveCommonPoint)) && !NOTparallel && !l1.StartPoint.Equals(l1.EndPoint)) { room.Lines.Add(l1); } } //TODO:if there is room, we may move it, if there is no perpendicular line in that room -- but be careful of that other room if (roomsTouchingStartPoint.Any() && !l1.StartPoint.Equals(l1.EndPoint)) { if (!areweMovingOnLoopLine && !room.Lines.Contains(l1)) { room.Lines.Add(l1); //this makes it easier to remove the small lines later } foreach (_Room room1 in roomsTouchingStartPoint) { if (!room1.Lines.Contains(l1)) { room1.Lines.Add(l1); } } } } if (loopAndToMoveCommonPoint != null && loopAndToMoveCommonPoint.Equals(lineToMove.EndPoint)) { bool areweMovingOnLoopLine = _Model.IsOnLineButNotEndPoint(l2.EndPoint, lineInLoop); if (!roomsTouchingEndPoint.Any()) { _Point objA = lineInLoop.GetNV(true); _Point objB = lineToMove.GetNV(true); bool NOTparallel = AreNotParralel(objA, objB); if (lineInLoop.StartPoint.Equals(loopAndToMoveCommonPoint) && (NOTparallel)) { lineInLoop.StartPoint = lineInLoop.StartPoint.Move(moveVector); } if (lineInLoop.EndPoint.Equals(loopAndToMoveCommonPoint) && (NOTparallel)) { lineInLoop.EndPoint = lineInLoop.EndPoint.Move(moveVector); } if (lineInLoop.StartPoint.Equals(lineInLoop.EndPoint)) { linesToRemove.Add(lineInLoop); } if ((lineInLoop.EndPoint.Equals(loopAndToMoveCommonPoint) || lineInLoop.StartPoint.Equals(loopAndToMoveCommonPoint)) && !NOTparallel && !l2.StartPoint.Equals(l2.EndPoint)) { room.Lines.Add(l2); } } if (roomsTouchingEndPoint.Any() && !l2.StartPoint.Equals(l2.EndPoint)) { if (!areweMovingOnLoopLine && !room.Lines.Contains(l2)) { room.Lines.Add(l2); } foreach (_Room room2 in roomsTouchingEndPoint) { if (!room2.Lines.Contains(l2)) { room2.Lines.Add(l2); } } } } } room.Lines.Insert(linetoMoveOriginal, movedLine); foreach (var line in linesToRemove) { room.Lines.Remove(line); } //shouldBeTrue = room.CanGetBoundarySorted(); } foreach (_Room room in roomsContainingTheLineToMove) { bool shouldBeTrue = room.CanGetBoundarySorted(); TryToDivideRoomLinesWithL1L2(room, l1, l2); TryToCatchIfGlobalCase(room, movedLine); shouldBeTrue = room.CanGetBoundarySorted(); if (!shouldBeTrue) { //throw new Exception("should be sortable, if i cant figure it out, mark as invalid state"); IsInInvalidState = true; } } foreach (_Room room in roomsTouchingEndPoint) { TryToDivideRoomLinesWithL1L2(room, l1, l2); TryToRemoveRemainderLines(room, l1, l2); bool shouldBeTrue = room.CanGetBoundarySorted(); if (!shouldBeTrue) { //throw new Exception("should be sortable, if i cant figure it out, mark as invalid state IsInInvalidState = true; } } foreach (_Room room in roomsTouchingStartPoint) { TryToDivideRoomLinesWithL1L2(room, l1, l2); TryToRemoveRemainderLines(room, l1, l2); bool shouldBeTrue = room.CanGetBoundarySorted(); if (!shouldBeTrue) { //throw new Exception("should be sortable, if i cant figure it out, mark as invalid state"); IsInInvalidState = true; } } foreach (_Room room in roomsTouchingStartPointOnlyAndHaveNoParallelLines) { TryToRemoveRemainderLines(room, l1, l2); bool shouldBeTrue = room.CanGetBoundarySorted(); if (!shouldBeTrue) { IsInInvalidState = true; } } foreach (_Room room in roomsTouchingEndPointOnlyAndHaveNoParalellLines) { TryToRemoveRemainderLines(room, l1, l2); bool shouldBeTrue = room.CanGetBoundarySorted(); if (!shouldBeTrue) { IsInInvalidState = true; } } List <_Room> sumrooms = new List <_Room>(); sumrooms.AddRange(roomsContainingTheLineToMove); sumrooms.AddRange(roomsTouchingStartPoint); sumrooms.AddRange(roomsTouchingEndPoint); //this handles null lines, can be removed at any time, probably should do it before sorting foreach (_Room room in sumrooms) { for (var index = 0; index < room.Lines.Count; index++) { _Line roomLine = room.Lines[index]; if (roomLine.StartPoint.Equals(roomLine.EndPoint)) { room.Lines.Remove(roomLine); } } } //GC.Collect(); //only need to join the same line //but why after? we could handle upon creation moveStepsCount++; }