public static Pointf Reflect(Pointf inDirection, Pointf inNormal) { return(-2 * Pointf.Dot(inNormal, inDirection) * inNormal + inDirection); }
void CalcGraphStats() { double segmentLengthSum = 0; int segmentCount = 0; double extremeLength = 0; Pointf extreme1 = Pointf.zero; Pointf extreme2 = Pointf.zero; int n = puzzle.stateNodes.Count; for (int i = 0; i < n; i++) { PuzzleStateNode node1 = puzzle.stateNodes[i]; for (int j = 0; j < i; j++) { PuzzleStateNode node2 = puzzle.stateNodes[j]; Pointf vector = node2.point - node1.point; double len = vector.magnitude; double dist = distances[i, j]; if (dist == 1) { segmentCount++; segmentLengthSum += len; } if (len > extremeLength) { extremeLength = len; extreme1 = node1.point; extreme2 = node2.point; } } } if (segmentCount == 0) { centerTarget = Pointf.zero; diameterTarget = 0; angleTarget = 0; } else { segmentLength = segmentLengthSum / segmentCount; centerTarget = (extreme2 + extreme1) * 0.5; Pointf mainAxis = (extreme2 - extreme1); diameterTarget = mainAxis.magnitude; mainAxis = mainAxis / diameterTarget; Pointf axis2 = new Pointf(-mainAxis.y, mainAxis.x); double projectedMin = double.MaxValue; double projectedMax = double.MinValue; for (int i = 0; i < n; i++) { Pointf p = puzzle.stateNodes[i].point; Pointf rel = p - centerTarget; double relOnAxis2 = Pointf.Dot(rel, axis2); projectedMin = Math.Min(projectedMin, relOnAxis2); projectedMax = Math.Max(projectedMax, relOnAxis2); } angleTarget = Math.Atan2(mainAxis.x, -mainAxis.y); centerTarget += axis2 * (projectedMin + projectedMax) * 0.5; diameterTarget /= segmentLength; } }