// Copyright (C) Stichting Deltares 2018. All rights reserved.
//
// This file is part of Ringtoets.
//
// Ringtoets is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Core.Common.Base.Geometry;
namespace Ringtoets.MacroStabilityInwards.Data.TestUtil
{
///
/// The class helps to construct collections of points by reading a string (from file or directly) and
/// transforming this in objects that can be used in tests.
///
public static class Segment2DLoopCollectionHelper
{
///
/// Creates a loop from a given string. The string needs to be formatted as follows.
///
/// - First line contains the number of lines (n).
/// - The n following lines contain a number of digits.
/// - Each digit is a point and should be unique.
///
/// Example string:
///
/// "3" + Environment.NewLine +
/// "..1.." + Environment.NewLine +
/// "3...." + Environment.NewLine +
/// "...2."
///
///
/// The (correctly formatted) string representing a grid with points.
/// The of which describe a loop.
public static List CreateFromString(string s)
{
var points = new SortedDictionary();
string[] lines = s.Split(new[]
{
Environment.NewLine
}, StringSplitOptions.None);
int height = int.Parse(lines[0]);
var lineIndex = 1;
for (int y = height - 1; y >= 0; y--, lineIndex++)
{
foreach (Tuple tuple in AllIndexesOfDigit(lines[lineIndex]))
{
points.Add(tuple.Item1, new Point2D(tuple.Item2, y));
}
}
return CreateLoop(points);
}
private static List CreateLoop(SortedDictionary points)
{
var loop = new List(points.Count);
int count = points.Values.Count;
for (var i = 0; i < count; i++)
{
Point2D firstPoint = points.Values.ElementAt(i);
Point2D secondPoint = points.Values.ElementAt((i + 1) % count);
loop.Add(new Segment2D(firstPoint, secondPoint));
}
return loop;
}
///
/// Returns a of if .
/// The first item in the tuple contains the digit and the second item contains its index.
///
/// The line which contains digits.
/// A of of
/// which contains the digits and the index of those digits.
/// Thrown when the regex magically matches more or less than it should
/// have (1 digit).
private static IEnumerable> AllIndexesOfDigit(string line)
{
const string guess = @"\d";
MatchCollection matches = Regex.Matches(line, guess);
foreach (Match match in matches)
{
int digit;
try
{
digit = int.Parse(match.Value);
}
catch (ArgumentNullException e)
{
throw new Exception(e.Message, e);
}
catch (FormatException e)
{
throw new Exception(e.Message, e);
}
catch (OverflowException e)
{
throw new Exception(e.Message, e);
}
yield return Tuple.Create(digit, match.Index);
}
}
}
}