Index: DeltaShell.sln =================================================================== diff -u -r1450c6e12cbd3358c66a9efec22203c988af78ed -rb3fa1606efddd3bed496c2844a495ff92347fa44 --- DeltaShell.sln (.../DeltaShell.sln) (revision 1450c6e12cbd3358c66a9efec22203c988af78ed) +++ DeltaShell.sln (.../DeltaShell.sln) (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -126,7 +126,7 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wti.Data", "src\Plugins\Ringtoets\Piping\src\Ringtoets.Piping.Data\Wti.Data.csproj", "{CE994CC9-6F6A-48AC-B4BE-02C30A21F4DB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wti.IO", "src\Plugins\Wti\Wti.IO\Wti.IO.csproj", "{35B87B7A-7F50-4139-B563-589EE522B1ED}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wti.IO", "src\Plugins\Ringtoets\Piping\src\Ringtoets.Piping.IO\Wti.IO.csproj", "{35B87B7A-7F50-4139-B563-589EE522B1ED}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wti.Forms", "src\Plugins\Ringtoets\Piping\src\Ringtoets.Piping.Forms\Wti.Forms.csproj", "{7CD038E1-E111-4969-ACED-22C5BD2974E1}" EndProject @@ -140,7 +140,7 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wti.Forms.Test", "src\Plugins\Ringtoets\Piping\test\Ringtoets.Piping.Forms.Test\Wti.Forms.Test.csproj", "{622A8282-D872-4DD5-8B70-578A403F74FF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wti.IO.Test", "test\Plugins\Wti\Wti.IO.Test\Wti.IO.Test.csproj", "{E4B0E068-F1A3-47BA-965F-0EC1E78E530A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wti.IO.Test", "src\Plugins\Ringtoets\Piping\test\Ringtoets.Piping.IO.Test\Wti.IO.Test.csproj", "{E4B0E068-F1A3-47BA-965F-0EC1E78E530A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ringtoets.Piping.Plugin.Test", "src\Plugins\Ringtoets\Piping\test\Ringtoets.Piping.Plugin.Test\Ringtoets.Piping.Plugin.Test.csproj", "{9A5C8069-520E-49D3-AA62-E8FB19614A27}" EndProject @@ -520,23 +520,23 @@ {07206938-9671-4DC7-BDE4-35B0F6E20DBC} = {A300D2BD-2E91-4EA7-A421-646EE7B5118B} {4FDA4BD2-2C84-4C7C-9908-818884D52DBB} = {A300D2BD-2E91-4EA7-A421-646EE7B5118B} {E0990383-FB2E-47D1-99CD-9B9FA2929E5B} = {A300D2BD-2E91-4EA7-A421-646EE7B5118B} - {35B87B7A-7F50-4139-B563-589EE522B1ED} = {C9DA93BC-1034-4D15-AD4E-773E3F560179} {F3A82DA4-A377-4009-A424-EFC8839913ED} = {5A029776-37C6-4622-A4E9-9DB9E8E935AB} {0FA77E45-C347-4677-9DA0-4C330D1440D5} = {F3A82DA4-A377-4009-A424-EFC8839913ED} {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} = {F3A82DA4-A377-4009-A424-EFC8839913ED} + {1D3D58B6-EF7E-401E-92A0-104067D222EE} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} {10B8D63D-87E8-46DF-ACA9-A8CF22EE8FB5} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} {CE994CC9-6F6A-48AC-B4BE-02C30A21F4DB} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} - {D64E4F0E-E341-496F-82B2-941AD202B4E3} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} - {1D3D58B6-EF7E-401E-92A0-104067D222EE} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} {7CD038E1-E111-4969-ACED-22C5BD2974E1} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} - {E4B0E068-F1A3-47BA-965F-0EC1E78E530A} = {BC862348-6B4E-49EA-9099-2E5BE6DC183A} + {D64E4F0E-E341-496F-82B2-941AD202B4E3} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} + {35B87B7A-7F50-4139-B563-589EE522B1ED} = {0FA77E45-C347-4677-9DA0-4C330D1440D5} + {622A8282-D872-4DD5-8B70-578A403F74FF} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} {9A5C8069-520E-49D3-AA62-E8FB19614A27} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} {19EB1C52-D90B-40F2-A7AF-364CC5D89F68} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} {D783543B-46A1-4848-A812-AF5A5259ED7E} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} {27E0A5C9-3ABF-426A-A3DA-7D0B83A218C8} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} {955E574D-67CE-4347-AA6B-7DF8A04ED754} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} {91389DA2-3FF4-4559-90B3-4061549789DD} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} - {622A8282-D872-4DD5-8B70-578A403F74FF} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} + {E4B0E068-F1A3-47BA-965F-0EC1E78E530A} = {C2EEB390-385B-4471-ABB8-9C1F1A8D0C11} {3CCB05DB-C7B3-4EF7-B41D-22B6D2A3774E} = {C4E268AD-A25B-4F47-8F92-E5137FDF7CC7} {4AD99020-8612-46E5-A313-F9ADA7B196E4} = {0D2E4E16-EE0A-4E50-9218-947B1D91C84D} EndGlobalSection Index: packages/repositories.config =================================================================== diff -u -rd80c8343ac1824759a0c42c3347c3900b67004b1 -rb3fa1606efddd3bed496c2844a495ff92347fa44 --- packages/repositories.config (.../repositories.config) (revision d80c8343ac1824759a0c42c3347c3900b67004b1) +++ packages/repositories.config (.../repositories.config) (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -15,8 +15,8 @@ + - Index: src/DeltaShell/DeltaShell.Gui/DeltaShell.Gui.csproj =================================================================== diff -u -r53a2d662c6893cb7e63dc150aaab6c2b3e9db769 -rb3fa1606efddd3bed496c2844a495ff92347fa44 --- src/DeltaShell/DeltaShell.Gui/DeltaShell.Gui.csproj (.../DeltaShell.Gui.csproj) (revision 53a2d662c6893cb7e63dc150aaab6c2b3e9db769) +++ src/DeltaShell/DeltaShell.Gui/DeltaShell.Gui.csproj (.../DeltaShell.Gui.csproj) (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -304,7 +304,7 @@ {ce994cc9-6f6a-48ac-b4be-02c30a21f4db} Wti.Data - + {7cd038e1-e111-4969-aced-22c5bd2974e1} Wti.Forms Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2D.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2D.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2D.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Wti.Data; +using Wti.IO.Calculation; +using Wti.IO.Properties; + +namespace Wti.IO.Builders +{ + /// + /// This class represents objects which were imported from a DSoilModel database. This class + /// + internal class SoilLayer2D + { + /// + /// Creates a new instance of . + /// + public SoilLayer2D() + { + InnerLoops = new Collection>(); + } + + /// + /// Gets the outer loop of the as a of . + /// + internal HashSet OuterLoop { get; set; } + + /// + /// Gets the of inner loops (as of ) of the . + /// + internal Collection> InnerLoops { get; private set; } + + /// + /// Constructs a (1D) based on the and set for the . + /// + /// The point from which to take a 1D profile. + /// The bottom level of the . + /// + internal IEnumerable AsPipingSoilLayers(double atX, out double bottom) + { + bottom = Double.MaxValue; + var result = new Collection(); + if (OuterLoop != null) + { + Collection outerLoopIntersectionHeights = GetLoopIntersectionHeights(OuterLoop, atX); + + if (outerLoopIntersectionHeights.Count > 0) + { + IEnumerable> innerLoopsIntersectionHeights = InnerLoops.Select(loop => GetLoopIntersectionHeights(loop, atX)); + IEnumerable> innerLoopIntersectionHeightPairs = GetOrderedStartAndEndPairsIn1D(innerLoopsIntersectionHeights).ToList(); + IEnumerable> outerLoopIntersectionHeightPairs = GetOrderedStartAndEndPairsIn1D(outerLoopIntersectionHeights).ToList(); + + var currentBottom = outerLoopIntersectionHeightPairs.First().Item1; + var heights = new List(); + heights.AddRange(innerLoopIntersectionHeightPairs.Where(p => p.Item1 >= currentBottom).Select(p => p.Item1)); + heights.AddRange(outerLoopIntersectionHeightPairs.Select(p => p.Item2)); + + foreach (var height in heights.Where(height => !innerLoopIntersectionHeightPairs.Any(tuple => HeightInInnerLoop(tuple, height)))) + { + result.Add(new PipingSoilLayer(height)); + } + bottom = EnsureBottomOutsideInnerLoop(innerLoopIntersectionHeightPairs, currentBottom); + } + } + return result; + } + + private double EnsureBottomOutsideInnerLoop(IEnumerable> innerLoopIntersectionHeightPairs, double bottom) + { + var newBottom = bottom; + var heigthPairArray = innerLoopIntersectionHeightPairs.ToList(); + var overlappingInnerLoop = heigthPairArray.FirstOrDefault(t => BottomInInnerLoop(t, newBottom)); + + while (overlappingInnerLoop != null) + { + newBottom = overlappingInnerLoop.Item2; + overlappingInnerLoop = heigthPairArray.FirstOrDefault(t => BottomInInnerLoop(t, newBottom)); + } + return newBottom; + } + + private bool HeightInInnerLoop(Tuple tuple, double height) + { + return height <= tuple.Item2 && height > tuple.Item1; + } + + private bool BottomInInnerLoop(Tuple tuple, double height) + { + return height < tuple.Item2 && height >= tuple.Item1; + } + + private IEnumerable> GetOrderedStartAndEndPairsIn1D(IEnumerable> innerLoopsIntersectionPoints) + { + Collection> result = new Collection>(); + foreach (var innerLoopIntersectionPoints in innerLoopsIntersectionPoints) + { + foreach (var tuple in GetOrderedStartAndEndPairsIn1D(innerLoopIntersectionPoints)) + { + result.Add(tuple); + } + } + return result; + } + + private static Collection> GetOrderedStartAndEndPairsIn1D(IEnumerable innerLoopIntersectionPoints) + { + var result = new Collection>(); + var orderedHeights = innerLoopIntersectionPoints.OrderBy(v => v).ToList(); + for (int i = 0; i < orderedHeights.Count; i = i+2) + { + var first = orderedHeights[i]; + var second = orderedHeights[i+1]; + result.Add(new Tuple(first, second)); + } + return result; + } + + private Collection GetLoopIntersectionHeights(HashSet loop, double atX) + { + Collection intersectionPointY = new Collection(); ; + for (int segmentIndex = 0; segmentIndex < loop.Count; segmentIndex++) + { + var intersectionPoint = GetSegmentIntersectionAtX(loop, segmentIndex, atX); + + if (intersectionPoint.Length > 0) + { + intersectionPointY.Add(intersectionPoint[1]); + } + else if (IsVerticalAtX(GetSegmentWithStartAtIndex(loop, segmentIndex), atX)) + { + throw new SoilLayer2DConversionException(String.Format(Resources.Error_CanNotDetermine1DProfileWithVerticalSegmentsAtX, atX)); + } + } + return intersectionPointY; + } + + private bool IsVerticalAtX(Point3D[] segment, double atX) + { + return Math.Abs(segment[0].X - atX) + Math.Abs(segment[1].X - atX) < Math2D.EpsilonForComparisons; + } + + private static Point3D[] GetSegmentWithStartAtIndex(HashSet loop, int i) + { + var current = loop.ElementAt(i); + var next = loop.ElementAt((i + 1) % loop.Count); + + return new[] + { + current, + next + }; + } + + private static double[] GetSegmentIntersectionAtX(HashSet loop, int segmentIndex, double atX) + { + Point3D[] segment = GetSegmentWithStartAtIndex(loop, segmentIndex); + + return Math2D.LineSegmentIntersectionWithLine(new[] + { + segment[0].X, + segment[1].X, + atX, + atX + }, new[] + { + segment[0].Z, + segment[1].Z, + 0, + 1 + }); + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2DConversionException.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2DConversionException.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2DConversionException.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,37 @@ +using System; +using Wti.Data; + +namespace Wti.IO.Builders +{ + /// + /// Exception thrown when something went wrong while converting to . + /// + public class SoilLayer2DConversionException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public SoilLayer2DConversionException() + { + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The message that describes the error. + public SoilLayer2DConversionException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class with a specified error message + /// and a reference to the inner exception that is the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a + /// null reference if no inner exception is specified. + public SoilLayer2DConversionException(string message, Exception innerException) : base(message, innerException) { } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilProfileBuilder.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilProfileBuilder.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilProfileBuilder.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Wti.Data; +using Wti.IO.Properties; + +namespace Wti.IO.Builders +{ + /// + /// Constructs a 1d Soil Profile based on definitions of . + /// + internal class SoilProfileBuilder + { + private readonly ICollection layers = new Collection(); + + /// + /// Creates a new instance of with the supposed name for the new + /// and the point at which a 1D profile should be obtained from the 2D profile. + /// + /// The name for the constructed by the . + /// The x position from which to obtain a 1D profile. + internal SoilProfileBuilder(string profileName, double atX) + { + if (double.IsNaN(atX)) + { + throw new ArgumentException(Resources.Error_SoilProfileBuilderCantDetermineIntersectAtDoubleNaN); + } + ProfileName = profileName; + AtX = atX; + Bottom = double.MaxValue; + } + + /// + /// Adds a new to the profile. + /// + /// The to add to the profile. + /// The . + internal SoilProfileBuilder Add(SoilLayer2D soilLayer) + { + double bottom; + foreach (PipingSoilLayer layer in soilLayer.AsPipingSoilLayers(AtX, out bottom)) + { + layers.Add(layer); + } + Bottom = Math.Min(Bottom, bottom); + return this; + } + + /// + /// Creates a new instance of . + /// + /// A new . + internal PipingSoilProfile Build() + { + return new PipingSoilProfile(ProfileName, Bottom, layers); + } + + private double Bottom { get; set; } + + private double AtX { get; set; } + + private string ProfileName { get; set; } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Calculation/Math2D.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Calculation/Math2D.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Calculation/Math2D.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,138 @@ +using System; + +namespace Wti.IO.Calculation +{ + /// + /// This class contains general mathematical routines for 2D lines. + /// + public static class Math2D + { + /// + /// Constant which is used to precision errors in comparisons. + /// + public const double EpsilonForComparisons = 1e-8; + + /// + /// Tries to find the point where two line segments intersect with each other. Note that if the lines are parallel, no intersection point is returned. + /// + /// X coordinates of the segments. Should have matching y coordinates in . + /// Y coordinates of the segments. Should have matching x coordinates in . + /// + public static double[] LineSegmentIntersectionWithLineSegment(double[] segmentsX, double[] segmentsY) + { + var numberOfPoints = 4; + if (segmentsX.Length != numberOfPoints || segmentsY.Length != numberOfPoints) + { + throw new ArgumentException(String.Format("Collections of segments' x and y coordinates need to have length of {0}.", numberOfPoints)); + } + var extraPolatedIntersectionPoint = LineSegmentIntersectionWithLine(segmentsX, segmentsY); + + if (extraPolatedIntersectionPoint.Length == 2) + { + var onSecondSegment = IsBetween(new[] + { + segmentsX[2], + segmentsX[3], + extraPolatedIntersectionPoint[0] + }, new[] + { + segmentsY[2], + segmentsY[3], + extraPolatedIntersectionPoint[1] + }); + if (onSecondSegment) + { + return extraPolatedIntersectionPoint; + } + } + return new double[0]; + } + + /// + /// Tries to find the point where the line segment intersects with the line. Note that if the segment and the line are parallel, no intersection point is returned. + /// + /// X coordinates of the segment and line. Should have matching y coordinates in . + /// Y coordinates of the segment and line. Should have matching x coordinates in . + /// + public static double[] LineSegmentIntersectionWithLine(double[] segmentsX, double[] segmentsY) + { + var extraPolatedIntersectionPoint = LineIntersectionWithLine(segmentsX, segmentsY); + + if (extraPolatedIntersectionPoint.Length == 2) + { + var onFirstSegment = IsBetween(new[] + { + segmentsX[0], + segmentsX[1], + extraPolatedIntersectionPoint[0] + }, new[] + { + segmentsY[0], + segmentsY[1], + extraPolatedIntersectionPoint[1] + }); + if (onFirstSegment) + { + return extraPolatedIntersectionPoint; + } + } + return new double[0]; + } + + /// Taken from: https://www.topcoder.com/community/data-science/data-science-tutorials/geometry-concepts-line-intersection-and-its-applications/ . + private static double[] LineIntersectionWithLine(double[] linesX, double[] linesY) + { + var numberOfPoints = 4; + if (linesX.Length != numberOfPoints || linesY.Length != numberOfPoints) + { + throw new ArgumentException(String.Format("Collections of lines' x and y coordinates need to have length of {0}", numberOfPoints)); + } + + var aLine = linesY[1] - linesY[0]; + var bLine = linesX[0] - linesX[1]; + var cLine = aLine * linesX[0] + bLine * linesY[0]; + + var aOtherLine = linesY[3] - linesY[2]; + var bOtherLine = linesX[2] - linesX[3]; + var cOtherLine = aOtherLine * linesX[2] + bOtherLine * linesY[2]; + + var determinant = aLine*bOtherLine - aOtherLine*bLine; + if (Math.Abs(determinant) < EpsilonForComparisons) + { + return new double[0]; + } + + return new[] + { + (bOtherLine*cLine - bLine*cOtherLine)/determinant, + (aLine*cOtherLine - aOtherLine*cLine)/determinant + }; + } + + /// + /// Checks whether point [2],[2] lies between [0],[0] + /// and [1],[1]. + /// + /// X-coordinates of the 3 points. + /// Y-coordinates of the 3 points. + /// True if point [2],[2] lies between [0],[0] + /// and [1],[1]. False otherwise. + private static bool IsBetween(double[] x, double[] y) + { + var crossProduct = (y[2] - y[0])*(x[1] - x[0]) - (x[2] - x[0])*(y[1] - y[0]); + if (Math.Abs(crossProduct) > EpsilonForComparisons) + { + return false; + } + + var dotProduct = (x[2] - x[0])*(x[1] - x[0]) + (y[2] - y[0])*(y[1] - y[0]); + if (dotProduct < 0) + { + return false; + } + + var squaredLengthSegment = (x[1] - x[0])*(x[1] - x[0]) + (y[1] - y[0])*(y[1] - y[0]); + return dotProduct <= squaredLengthSegment; + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/CriticalFileReadException.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/CriticalFileReadException.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/CriticalFileReadException.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,32 @@ +using System; + +namespace Wti.IO.Exceptions +{ + /// + /// The exception that is thrown when a file reader class encounters a critical error + /// during the read. + /// + public class CriticalFileReadException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public CriticalFileReadException(){} + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The error message that explains the reason for the exception. + public CriticalFileReadException(string message) : base(message){} + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that is + /// the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public CriticalFileReadException(string message, Exception inner) : base(message, inner) { } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/LineParseException.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/LineParseException.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/LineParseException.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,33 @@ +using System; + +namespace Wti.IO.Exceptions +{ + /// + /// The exception that is thrown when a file reader class encounters an error while + /// parsing a row/line during the read. + /// + public class LineParseException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public LineParseException() { } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The error message that explains the reason for the exception. + public LineParseException(string message) : base(message) { } + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that is + /// the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, + /// or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public LineParseException(string message, Exception inner) : base(message, inner) { } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/PipingSoilProfileReadException.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/PipingSoilProfileReadException.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Exceptions/PipingSoilProfileReadException.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,37 @@ +using System; +using Wti.Data; + +namespace Wti.IO.Exceptions +{ + /// + /// Exception thrown when something went wrong while reading in . + /// + public class PipingSoilProfileReadException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public PipingSoilProfileReadException() + { + } + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The message that describes the error. + public PipingSoilProfileReadException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class with a specified error message + /// and a reference to the inner exception that is the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a + /// null reference if no inner exception is specified. + public PipingSoilProfileReadException(string message, Exception innerException) : base(message, innerException) { } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilLayer2DReader.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilLayer2DReader.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilLayer2DReader.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Xml; +using Wti.Data; +using Wti.IO.Builders; + +namespace Wti.IO +{ + /// + /// This class is responsible for reading an array of bytes and interpret this as a XML document, which contains information about + /// the geometry of a . + /// + internal class PipingSoilLayer2DReader + { + private const string outerLoopElementName = "OuterLoop"; + private const string innerLoopElementName = "InnerLoop"; + private const string endPointElementName = "EndPoint"; + private const string headPointElementName = "HeadPoint"; + private const string xElementName = "X"; + private const string yElementName = "Y"; + private const string zElementName = "Z"; + + private readonly XmlTextReader xmlTextReader; + + /// + /// Constructs a new , which uses the as the source of the + /// geometry for a . + /// + /// An array of which contains the information of a + /// in an XML document. + /// Thrown when is null. + internal PipingSoilLayer2DReader(byte[] geometry) + { + xmlTextReader = new XmlTextReader(new MemoryStream(geometry)); + } + + /// + /// Reads the XML document and from this obtains the required information and constructs a based + /// on this information. + /// + /// A new with information taken from the XML document. + /// When reading from the XML document of the failed. + internal SoilLayer2D Read() + { + var pipingSoilLayer = new SoilLayer2D(); + + while (xmlTextReader.Read()) + { + HashSet outerLoop; + HashSet innerLoop; + if (TryParseLoop(outerLoopElementName, out outerLoop)) + { + pipingSoilLayer.OuterLoop = outerLoop; + } + if (TryParseLoop(innerLoopElementName, out innerLoop)) + { + pipingSoilLayer.InnerLoops.Add(innerLoop); + } + } + + return pipingSoilLayer; + } + + /// + /// Tries to parse the element with the given , which the reader should be currently pointing at, as a loop. + /// + /// The name of the element which the reader should be currently pointing at. + /// The result of parsing the element as a loop. null if the current element's name does not match . + /// True if the reader currently points to an element with name . False otherwise. + private bool TryParseLoop(String elementName, out HashSet loop) + { + loop = null; + + if (IsElementWithName(elementName)) + { + loop = new HashSet(); + + if (!IsEmptyElement()) + { + while (xmlTextReader.Read() && !IsEndElementWithName(elementName)) + { + Point3D parsedPoint; + if (TryParsePoint(out parsedPoint)) + { + loop.Add(parsedPoint); + } + } + } + return true; + } + return false; + } + + /// + /// Finds out whether the element which the reader is currently pointing at is empty. + /// + /// True if the element is empty. False otherwise. + private bool IsEmptyElement() + { + return xmlTextReader.IsEmptyElement; + } + + /// + /// Tries to parse the element which the reader is currently pointing at as a point. + /// + /// The result of parsing the element as a point. null if current element is not a head or end point. + /// True if the reader currently points to an element with name or . False otherwise. + private bool TryParsePoint(out Point3D point) + { + point = null; + + if (IsElementWithName(headPointElementName) || IsElementWithName(endPointElementName)) + { + var pointValues = ReadChildValues(); + point = new Point3D + { + X = double.Parse(pointValues[xElementName], CultureInfo.InvariantCulture), + Y = double.Parse(pointValues[yElementName], CultureInfo.InvariantCulture), + Z = double.Parse(pointValues[zElementName], CultureInfo.InvariantCulture) + }; + return true; + } + return false; + } + + /// + /// Reads the name and values for the children of the current element and puts them in a name indexed dictionary. + /// + /// A . For each entry, key is equal to child element name and value is equal to the value of the child element's text node. + private Dictionary ReadChildValues() + { + string elementName = xmlTextReader.Name; + var nodeSibblings = new Dictionary(); + + while (xmlTextReader.Read() && !IsEndElementWithName(elementName)) + { + if (xmlTextReader.NodeType == XmlNodeType.Element) + { + nodeSibblings[xmlTextReader.Name] = xmlTextReader.ReadString(); + } + } + + return nodeSibblings; + } + + /// + /// Checks whether the element the reader is currently pointing at is of type and has a name equal to . + /// + /// The name which the element should have. + /// True if the current element has type and its name is equal to . + private bool IsElementWithName(string name) + { + var isElement = xmlTextReader.NodeType == XmlNodeType.Element; + var isPoint = xmlTextReader.Name == name; + + return isElement && isPoint; + } + /// + /// Checks whether the element the reader is currently pointing at is of type and has a name equal to . + /// + /// The name which the end element should have. + /// True if the current element has type and its name is equal to . + private bool IsEndElementWithName(string name) + { + var isElement = xmlTextReader.NodeType == XmlNodeType.EndElement; + var isPoint = xmlTextReader.Name == name; + + return isElement && isPoint; + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using System.IO; +using System.Linq; +using System.Xml; +using Wti.Data; +using Wti.IO.Builders; +using Wti.IO.Exceptions; +using Wti.IO.Properties; + +namespace Wti.IO +{ + /// + /// This class reads a SqLite database file and constructs from this database. + /// The database is created with the DSoilModel application. + /// + public class PipingSoilProfileReader : IDisposable + { + private const int pipingMechanismId = 4; + private const int profileNameIndex = 0; + private const int profileLayerGeometryIndex = 1; + private const int intersectionXIndex = 3; + + private SQLiteConnection connection; + private SQLiteDataReader dataReader; + + /// + /// Creates a new instance of which will use the + /// as its source. + /// + /// + public PipingSoilProfileReader(string dbFile) + { + if (String.IsNullOrEmpty(dbFile)) + { + throw new ArgumentException(Resources.Error_PathMustBeSpecified); + } + if (!File.Exists(dbFile)) + { + throw new FileNotFoundException(String.Format(Resources.Error_File_0_does_not_exist, dbFile)); + } + + PrepareConnection(dbFile); + Connect(); + } + + /// + /// Creates instances of based on the database file of the . + /// + /// + /// Thrown when reading soil profile entries from the database failed. + /// Thrown when parsing the geometry of a soil layer failed. + public IEnumerable Read() + { + var pipingSoilProfiles = new Dictionary(); + + CreateDataReader(); + + while (dataReader.Read()) + { + var profileName = (string) dataReader[profileNameIndex]; + var intersectionX = (double) dataReader[intersectionXIndex]; + if (!pipingSoilProfiles.ContainsKey(profileName)) + { + pipingSoilProfiles.Add(profileName, new SoilProfileBuilder(profileName, intersectionX)); + } + + pipingSoilProfiles[profileName].Add(ReadPipingSoilLayer()); + } + + return pipingSoilProfiles.Select(keyValue => keyValue.Value.Build()); + } + + public void Dispose() + { + dataReader.Dispose(); + connection.Dispose(); + } + + private void PrepareConnection(string dbFile) + { + var connectionStringBuilder = new SQLiteConnectionStringBuilder + { + FailIfMissing = true, + DataSource = dbFile, + ReadOnly = true, + ForeignKeys = true + }; + + connection = new SQLiteConnection(connectionStringBuilder.ConnectionString); + } + + private void Connect() + { + try + { + connection.Open(); + } + catch (SQLiteException) + { + connection.Dispose(); + } + } + + private SoilLayer2D ReadPipingSoilLayer() + { + var columnValue = dataReader[profileLayerGeometryIndex]; + var geometry = (byte[]) columnValue; + return new PipingSoilLayer2DReader(geometry).Read(); + } + + /// + /// Creates a new data reader to use in this class, based on a query which returns all the known soil layers for which its profile has a X coordinate defined for piping. + /// + private void CreateDataReader() + { + var mechanismParameterName = "mechanism"; + var query = new SQLiteCommand(connection) + { + CommandText = string.Format( + "SELECT p.SP2D_Name, l.GeometrySurface, mat.MA_Name, mpl.X " + + "FROM MechanismPointLocation as m " + + "JOIN MechanismPointLocation as mpl ON p.SP2D_ID = mpl.SP2D_ID " + + "JOIN SoilProfile2D as p ON m.SP2D_ID = p.SP2D_ID " + + "JOIN SoilLayer2D as l ON l.SP2D_ID = p.SP2D_ID " + + "JOIN Materials as mat ON mat.MA_ID = l.MA_ID " + + "WHERE m.ME_ID = @{0} " + + "ORDER BY p.SP2D_ID, l.SP2D_ID", + mechanismParameterName) + }; + query.Parameters.Add(new SQLiteParameter + { + DbType = DbType.Int32, + Value = pipingMechanismId, + ParameterName = mechanismParameterName + }); + + try + { + dataReader = query.ExecuteReader(); + } + catch (SQLiteException e) + { + throw new PipingSoilProfileReadException(string.Format(Resources.Error_SoilProfileReadFromDatabase, connection.DataSource), e); + } + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSurfaceLinesCsvReader.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSurfaceLinesCsvReader.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSurfaceLinesCsvReader.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,404 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; + +using Wti.Data; +using Wti.IO.Exceptions; +using Wti.IO.Properties; + +namespace Wti.IO +{ + /// + /// File reader for a plain text file in comma-separated values format (*.csv), containing + /// data specifying surfacelines. + /// Expects data to be specified in the following format: + /// {ID};X1;Y1;Z1...;(Xn;Yn;Zn) + /// Where {ID} has to be a particular accepted text, and n triplets of doubles form the + /// 3D coordinates defining the geometric shape of the surfaceline.. + /// + public class PipingSurfaceLinesCsvReader : IDisposable + { + private const char separator = ';'; + + private readonly string[] acceptableLowerCaseIdNames = + { + "profielnaam", + "locationid" + }; + + private readonly string filePath; + + private readonly string[] expectedFirstCoordinateHeader = + { + "x1", + "y1", + "z1" + }; + + private StreamReader fileReader; + private int lineNumber; + + /// + /// Initializes a new instance of the class + /// and opens a given file path. + /// + /// The path to the file to be read. + /// is invalid. + public PipingSurfaceLinesCsvReader(string path) + { + ValidateFilePath(path); + + filePath = path; + } + + /// + /// Reads the file to determine the number of available + /// data rows. + /// + /// A value greater than or equal to 0. + /// A critical error has occurred, which may be caused by: + /// + /// File cannot be found at specified path. + /// The specified path is invalid, such as being on an unmapped drive. + /// Some other I/O related issue occurred, such as: path includes an incorrect + /// or invalid syntax for file name, directory name, or volume label. + /// There is insufficient memory to allocate a buffer for the returned string. + /// File incompatible for importing surface lines. + /// + /// + public int GetSurfaceLinesCount() + { + using (var reader = InitializeStreamReader(filePath)) + { + ValidateHeader(reader, 1); + + return CountNonEmptyLines(reader, 2); + } + } + + /// + /// Reads and consumes the next data row, parsing the data to create an instance + /// of . + /// + /// Return the parse surfaceline, or null when at the end of the file. + /// A critical error has occurred, which may be caused by: + /// + /// File cannot be found at specified path. + /// The specified path is invalid, such as being on an unmapped drive. + /// Some other I/O related issue occurred, such as: path includes an incorrect + /// or invalid syntax for file name, directory name, or volume label. + /// There is insufficient memory to allocate a buffer for the returned string. + /// File incompatible for importing surface lines. + /// + /// + /// A parse error has occurred for the current row, which may be caused by: + /// + /// The row doesn't contain any supported separator character. + /// The row contains a coordinate value that cannot be parsed as a double. + /// The row contains a number that is too big or too small to be represented with a double. + /// The row is missing an identifier value. + /// The row is missing values to form a surface line point. + /// + /// + public RingtoetsPipingSurfaceLine ReadLine() + { + if (fileReader == null) + { + fileReader = InitializeStreamReader(filePath); + + ValidateHeader(fileReader, 1); + lineNumber = 2; + } + + var readText = ReadLineAndHandleIOExceptions(fileReader, lineNumber); + if (readText != null) + { + try + { + var tokenizedString = TokenizeString(readText); + + var surfaceLineName = GetSurfaceLineName(tokenizedString); + var points = GetSurfaceLinePoints(tokenizedString); + + var surfaceLine = new RingtoetsPipingSurfaceLine + { + Name = surfaceLineName + }; + surfaceLine.SetGeometry(points); + return surfaceLine; + } + finally + { + lineNumber++; + } + } + + return null; + } + + public void Dispose() + { + if (fileReader != null) + { + fileReader.Dispose(); + fileReader = null; + } + } + + /// + /// Tokenizes a string using a separator character. + /// + /// The text. + /// The tokenized parts. + /// lacks separator character. + private string[] TokenizeString(string readText) + { + if (!readText.Contains(separator)) + { + var message = string.Format(Resources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_, + filePath, lineNumber, separator); + throw new LineParseException(message); + } + return readText.Split(separator); + } + + /// + /// Gets the 3D surface line points. + /// + /// The tokenized string. + /// + /// A parse error has occurred for the current row, which may be caused by: + /// + /// contains a coordinate value that cannot be parsed as a double. + /// contains a number that is too big or too small to be represented with a double. + /// is missing coordinate values to define a proper surface line point. + /// + /// + private Point3D[] GetSurfaceLinePoints(string[] tokenizedString) + { + const int expectedValuesForPoint = 3; + + var worldCoordinateValues = ParseWorldCoordinateValuesAndHandleParseErrors(tokenizedString); + if (worldCoordinateValues.Length % expectedValuesForPoint != 0) + { + var message = string.Format(Resources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet, + filePath, lineNumber); + throw new LineParseException(message); + } + + int coordinateCount = worldCoordinateValues.Length / expectedValuesForPoint; + var points = new Point3D[coordinateCount]; + for (int i = 0; i < coordinateCount; i++) + { + points[i] = new Point3D + { + X = worldCoordinateValues[i * expectedValuesForPoint], + Y = worldCoordinateValues[i * expectedValuesForPoint + 1], + Z = worldCoordinateValues[i * expectedValuesForPoint + 2] + }; + } + return points; + } + + /// + /// Gets the name of the surface line. + /// + /// The tokenized string from which the name should be extrated. + /// The name of the surface line. + /// Id value is null or empty. + private string GetSurfaceLineName(IList tokenizedString) + { + var name = tokenizedString[0].Trim(); + if (string.IsNullOrEmpty(name)) + { + var message = string.Format(Resources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId, + filePath, lineNumber); + throw new LineParseException(message); + } + return name; + } + + /// + /// Parses the world coordinate values and handles parse errors. + /// + /// The tokenized string. + /// + /// A parse error has occurred for the current row, which may be caused by: + /// + /// The row contains a coordinate value that cannot be parsed as a double. + /// The row contains a number that is too big or too small to be represented with a double. + /// + /// + private double[] ParseWorldCoordinateValuesAndHandleParseErrors(string[] tokenizedString) + { + try + { + return tokenizedString.Skip(1) + .Select(ts => Double.Parse(ts, CultureInfo.InvariantCulture)) + .ToArray(); + } + catch (FormatException e) + { + var message = string.Format(Resources.Error_File_0_has_not_double_Line_1_, + filePath, lineNumber); + throw new LineParseException(message, e); + } + catch (OverflowException e) + { + var message = string.Format(Resources.Error_File_0_Parsing_causes_overflow_Line_1_, + filePath, lineNumber); + throw new LineParseException(message, e); + } + } + + /// + /// Initializes the stream reader for a UTF8 encoded file. + /// + /// The path to the file to be read. + /// A UTF8 encoding configured stream reader opened on . + /// File/directory cannot be found or + /// some other I/O related problem occurred. + private static StreamReader InitializeStreamReader(string path) + { + try + { + return new StreamReader(path); + } + catch (FileNotFoundException e) + { + var message = string.Format(Resources.Error_File_0_does_not_exist, path); + throw new CriticalFileReadException(message, e); + } + catch (DirectoryNotFoundException e) + { + var message = string.Format(Resources.Error_Directory_in_path_0_missing, path); + throw new CriticalFileReadException(message, e); + } + catch (IOException e) + { + var message = string.Format(Resources.Error_General_IO_File_0_ErrorMessage_1_, path, e.Message); + throw new CriticalFileReadException(message, e); + } + } + + /// + /// Validates the header of the file. + /// + /// The reader, which is currently at the header row. + /// Row index used in error messaging. + /// The header is not in the required format. + private void ValidateHeader(TextReader reader, int currentLine) + { + var header = ReadLineAndHandleIOExceptions(reader, currentLine); + if (header != null) + { + if (!IsHeaderValid(header)) + { + var expectedMessage = string.Format(Resources.PipingSurfaceLinesCsvReader_File_0_invalid_header, filePath); + throw new CriticalFileReadException(expectedMessage); + } + } + else + { + var expectedMessage = string.Format(Resources.Error_File_0_empty, filePath); + throw new CriticalFileReadException(expectedMessage); + } + } + + /// + /// Counts the remaining non-empty lines. + /// + /// The reader at the row from which counting should start. + /// The current line, used for error messaging. + /// An integer greater than or equal to 0. + /// An I/O exception occurred. + private int CountNonEmptyLines(TextReader reader, int currentLine) + { + int count = 0, lineNumberForMessage = currentLine; + string line; + while ((line = ReadLineAndHandleIOExceptions(reader, lineNumberForMessage)) != null) + { + if (!String.IsNullOrWhiteSpace(line)) + { + count++; + } + lineNumberForMessage++; + } + return count; + } + + /// + /// Reads the next line and handles I/O exceptions. + /// + /// The opened text file reader. + /// Row number for error messaging. + /// The read line, or null when at the end of the file. + /// An critical I/O exception occurred. + private string ReadLineAndHandleIOExceptions(TextReader reader, int currentLine) + { + try + { + return reader.ReadLine(); + } + catch (OutOfMemoryException e) + { + var message = string.Format(Resources.Error_File_0_contains_Line_1_too_big, filePath, currentLine); + throw new CriticalFileReadException(message, e); + } + catch (IOException e) + { + var message = string.Format(Resources.Error_General_IO_File_0_ErrorMessage_1_, filePath, e.Message); + throw new CriticalFileReadException(message, e); + } + } + + private bool IsHeaderValid(string header) + { + var tokenizedHeader = header.Split(separator).Select(s => s.Trim().ToLowerInvariant()).ToArray(); + + // Check for valid id: + if (!acceptableLowerCaseIdNames.Contains(tokenizedHeader[0])) + { + return false; + } + + // CHeck for valid 1st coordinate in header: + bool valid = true; + for (int i = 0; i < expectedFirstCoordinateHeader.Length && valid; i++) + { + valid = tokenizedHeader[1 + i].Equals(expectedFirstCoordinateHeader[i]); + } + return valid; + } + + /// + /// Validates the file path. + /// + /// The file path to be validated. + /// is invalid. + private void ValidateFilePath(string path) + { + if (string.IsNullOrWhiteSpace(path)) + { + throw new ArgumentException(Resources.Error_PathMustBeSpecified); + } + + string name; + try + { + name = Path.GetFileName(path); + } + catch (ArgumentException e) + { + throw new ArgumentException(String.Format(Resources.Error_PathCannotContainCharacters_0_, + String.Join(", ", Path.GetInvalidFileNameChars())), e); + } + if (string.Empty == name) + { + throw new ArgumentException(Resources.Error_PathMustNotPointToFolder); + } + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/AssemblyInfo.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/AssemblyInfo.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/AssemblyInfo.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,8 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Wti.IO")] +[assembly: AssemblyProduct("Wti.IO")] +[assembly: Guid("f5af3cbe-d10c-42a5-b625-95222648aeaf")] +[assembly: InternalsVisibleTo("Wti.IO.Test")] \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.Designer.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.Designer.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.Designer.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,226 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Wti.IO.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wti.IO.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Kan geen 1D profiel bepalen wanneer segmenten in een 2D laag verticaal lopen op de gekozen positie: x = {0}.. + /// + public static string Error_CanNotDetermine1DProfileWithVerticalSegmentsAtX { + get { + return ResourceManager.GetString("Error_CanNotDetermine1DProfileWithVerticalSegmentsAtX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestandspad '{0}' verwijst naar een map die niet bestaat.. + /// + public static string Error_Directory_in_path_0_missing { + get { + return ResourceManager.GetString("Error_Directory_in_path_0_missing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand op '{0}' heeft op regel {1} teveel tekst om in het RAM geheugen opgeslagen te worden.. + /// + public static string Error_File_0_contains_Line_1_too_big { + get { + return ResourceManager.GetString("Error_File_0_contains_Line_1_too_big", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand op '{0}' bestaat niet.. + /// + public static string Error_File_0_does_not_exist { + get { + return ResourceManager.GetString("Error_File_0_does_not_exist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand op '{0}' is leeg.. + /// + public static string Error_File_0_empty { + get { + return ResourceManager.GetString("Error_File_0_empty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} een waarde dat geen getal is.. + /// + public static string Error_File_0_has_not_double_Line_1_ { + get { + return ResourceManager.GetString("Error_File_0_has_not_double_Line_1_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} een waarde dat te groot/klein is om ingelezen te worden.. + /// + public static string Error_File_0_Parsing_causes_overflow_Line_1_ { + get { + return ResourceManager.GetString("Error_File_0_Parsing_causes_overflow_Line_1_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Er is een onverwachte inleesfout opgetreden tijdens het lezen van het bestand '{0}': {1}. + /// + public static string Error_General_IO_File_0_ErrorMessage_1_ { + get { + return ResourceManager.GetString("Error_General_IO_File_0_ErrorMessage_1_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bestandspad mag niet de volgende tekens bevatten: {0}. + /// + public static string Error_PathCannotContainCharacters_0_ { + get { + return ResourceManager.GetString("Error_PathCannotContainCharacters_0_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bestandspad mag niet leeg of ongedefinieerd zijn.. + /// + public static string Error_PathMustBeSpecified { + get { + return ResourceManager.GetString("Error_PathMustBeSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bestandspad mag niet naar een map verwijzen.. + /// + public static string Error_PathMustNotPointToFolder { + get { + return ResourceManager.GetString("Error_PathMustNotPointToFolder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Geen geldige X waarde gevonden om intersectie te maken uit 2D profiel '{0}'.. + /// + public static string Error_SoilProfileBuilderCantDetermineIntersectAtDoubleNaN { + get { + return ResourceManager.GetString("Error_SoilProfileBuilderCantDetermineIntersectAtDoubleNaN", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kon geen ondergrond profielen verkrijgen van de database '{0}'.. + /// + public static string Error_SoilProfileReadFromDatabase { + get { + return ResourceManager.GetString("Error_SoilProfileReadFromDatabase", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand op '{0}' heeft op regel {1} teveel tekst om in het RAM geheugen opgeslagen te worden.. + /// + public static string Error_Unexpected_IOError_File_0_Line_1_ { + get { + return ResourceManager.GetString("Error_Unexpected_IOError_File_0_Line_1_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand op '{0}' is niet geschikt om dwarsdoorsneden uit te lezen (Verwachte header: locationid;X1;Y1;Z1).. + /// + public static string PipingSurfaceLinesCsvReader_File_0_invalid_header { + get { + return ResourceManager.GetString("PipingSurfaceLinesCsvReader_File_0_invalid_header", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} geen verwacht scheidingsteken (het karakter: {2}).. + /// + public static string PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_ { + get { + return ResourceManager.GetString("PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} ontbrekende waardes om een 3D (X,Y,Z) punt aan te maken.. + /// + public static string PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet { + get { + return ResourceManager.GetString("PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_tr" + + "iplet", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} heeft geen ID.. + /// + public static string PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId { + get { + return ResourceManager.GetString("PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId", resourceCulture); + } + } + } +} Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.resx =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.resx (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.resx (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bestandspad mag niet leeg of ongedefinieerd zijn. + + + Bestandspad mag niet naar een map verwijzen. + + + Bestandspad mag niet de volgende tekens bevatten: {0} + + + Het bestand op '{0}' bestaat niet. + + + Het bestandspad '{0}' verwijst naar een map die niet bestaat. + + + Het bestand op '{0}' heeft op regel {1} teveel tekst om in het RAM geheugen opgeslagen te worden. + + + Het bestand op '{0}' heeft op regel {1} teveel tekst om in het RAM geheugen opgeslagen te worden. + + + Er is een onverwachte inleesfout opgetreden tijdens het lezen van het bestand '{0}': {1} + + + Het bestand op '{0}' is leeg. + + + Het bestand op '{0}' is niet geschikt om dwarsdoorsneden uit te lezen (Verwachte header: locationid;X1;Y1;Z1). + + + Kon geen ondergrond profielen verkrijgen van de database '{0}'. + + + Geen geldige X waarde gevonden om intersectie te maken uit 2D profiel '{0}'. + + + Het bestand '{0}' heeft op regel {1} een waarde dat geen getal is. + + + Het bestand '{0}' heeft op regel {1} een waarde dat te groot/klein is om ingelezen te worden. + + + Het bestand '{0}' heeft op regel {1} heeft geen ID. + + + Het bestand '{0}' heeft op regel {1} geen verwacht scheidingsteken (het karakter: {2}). + + + Het bestand '{0}' heeft op regel {1} ontbrekende waardes om een 3D (X,Y,Z) punt aan te maken. + + + Kan geen 1D profiel bepalen wanneer segmenten in een 2D laag verticaal lopen op de gekozen positie: x = {0}. + + \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Wti.IO.csproj =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Wti.IO.csproj (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/Wti.IO.csproj (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,123 @@ + + + + + Debug + AnyCPU + {35B87B7A-7F50-4139-B563-589EE522B1ED} + Library + Properties + Wti.IO + Wti.IO + v4.0 + 512 + + + true + bin\Debug\ + 4 + DEBUG;TRACE + full + x86 + false + prompt + MinimumRecommendedRules.ruleset + bin\Debug\Wti.IO.XML + + + bin\Release\ + 4 + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + bin\Release\Wti.IO.XML + + + + Properties\GlobalAssembly.cs + + + + + + + + + + + + + + True + True + Resources.resx + + + + + {82b61d20-fd4b-49be-9252-5bf6e3ee4666} + DelftTools.Shell.Core + + + {c90b77da-e421-43cc-b82e-529651bc21ac} + Wti.Base + False + + + {ce994cc9-6f6a-48ac-b4be-02c30a21f4db} + Wti.Data + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll + + + + ..\..\..\..\..\..\packages\System.Data.SQLite.Core.1.0.98.1\lib\net40\System.Data.SQLite.dll + True + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.XML.dll + + + + + + + + SQLite.Interop.dll + Always + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/packages.config =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/packages.config (revision 0) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.IO/packages.config (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,4 @@ + + + + \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Ringtoets.Piping.Plugin.csproj =================================================================== diff -u -r1450c6e12cbd3358c66a9efec22203c988af78ed -rb3fa1606efddd3bed496c2844a495ff92347fa44 --- src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Ringtoets.Piping.Plugin.csproj (.../Ringtoets.Piping.Plugin.csproj) (revision 1450c6e12cbd3358c66a9efec22203c988af78ed) +++ src/Plugins/Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Ringtoets.Piping.Plugin.csproj (.../Ringtoets.Piping.Plugin.csproj) (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -111,6 +111,10 @@ {7cd038e1-e111-4969-aced-22c5bd2974e1} Wti.Forms + + {35b87b7a-7f50-4139-b563-589ee522b1ed} + Wti.IO + {10B8D63D-87E8-46DF-ACA9-A8CF22EE8FB5} Ringtoets.Piping.Service @@ -119,10 +123,6 @@ {ce994cc9-6f6a-48ac-b4be-02c30a21f4db} Wti.Data - - {35b87b7a-7f50-4139-b563-589ee522b1ed} - Wti.IO - Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Builders/SoilLayer2DTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Builders/SoilLayer2DTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Builders/SoilLayer2DTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,539 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Wti.Data; +using Wti.Data.TestUtil; +using Wti.IO.Builders; +using Wti.IO.Properties; + +namespace Wti.IO.Test.Builders +{ + public class SoilLayer2DTest + { + [Test] + public void DefaultConstructor_Always_NotInstantiatedOuterLoopAndEmptyInnerLoops() + { + // Call + var result = new SoilLayer2D(); + + // Assert + Assert.IsNull(result.OuterLoop); + CollectionAssert.IsEmpty(result.InnerLoops); + } + + [Test] + public void AsPipingSoilLayers_DefaultConstructed_ReturnsEmptyCollectionWithMaxValueBottom() + { + // Setup + var layer = new SoilLayer2D(); + double bottom; + + // Call + var result = layer.AsPipingSoilLayers(0.0, out bottom); + + // Assert + CollectionAssert.IsEmpty(result); + Assert.AreEqual(double.MaxValue, bottom); + } + + [Test] + public void AsPipingSoilLayers_WithOuterLoopNotIntersectingX_ReturnsEmptyCollectionWithMaxValueBottom() + { + // Setup + var layer = new SoilLayer2D + { + OuterLoop = new HashSet + { + new Point3D + { + X = 0.1, Z = new Random(22).NextDouble() + } + } + }; + double bottom; + + // Call + var result = layer.AsPipingSoilLayers(0.0, out bottom); + + // Assert + CollectionAssert.IsEmpty(result); + Assert.AreEqual(double.MaxValue, bottom); + } + + [Test] + public void AsPipingSoilLayers_WithOuterLoopIntersectingX_ReturnsBottomAndLayerWithTop() + { + // Setup + var expectedZ = new Random(22).NextDouble(); + var layer = new SoilLayer2D + { + OuterLoop = new HashSet + { + new Point3D + { + X = -0.1, Z = expectedZ + }, + new Point3D + { + X = 0.1, Z = expectedZ + } + } + }; + double bottom; + + // Call + var result = layer.AsPipingSoilLayers(0.0, out bottom).ToArray(); + + // Assert + Assert.AreEqual(1, result.Length); + Assert.AreEqual(expectedZ, bottom); + Assert.AreEqual(expectedZ, result[0].Top); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopComplex_ReturnsTwoLayers() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "..8.7...", + "..5.6...", + "..4..3..", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(2, result.Length); + Assert.AreEqual(1.0, bottom); + CollectionAssert.AreEquivalent(new[] { 5.0, 2.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopInnerLoopSimple_ReturnsTwoLayers() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + "........", + "..4..3..")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "...12...", + "........", + "........", + "...43...", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(2, result.Length); + Assert.AreEqual(0, bottom); + CollectionAssert.AreEquivalent(new [] {5.0, 1.0}, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopInnerLoopComplex_ReturnsThreeLayers() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + "........", + "..4..3..")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "...1.2..", + "...87...", + "...56...", + "...4.3..", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(3, result.Length); + Assert.AreEqual(0, bottom); + CollectionAssert.AreEquivalent(new[] { 5.0, 3.0, 1.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopMultipleInnerLoops_ReturnsThreeLayers() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + "........", + "..4..3..")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "...12...", + "...43...", + "........", + "........", + "........")); + + var innerLoop2 = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "........", + "........", + "........", + "...12...", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop, + innerLoop2 + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(3, result.Length); + Assert.AreEqual(0, bottom); + CollectionAssert.AreEquivalent(new[] { 5.0, 3.0, 1.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopOverlappingInnerLoop_ReturnsOneLayer() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + ".4....3.", + "........")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "........", + "........", + "...12...", + "........", + "...43...")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(1, result.Length); + Assert.AreEqual(2.0, bottom); + CollectionAssert.AreEquivalent(new[] { 5.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopOverlappingInnerLoopsFirstInnerLoopNotOverBottom_ReturnsOneLayer() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + ".4....3.", + "........")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "...12...", + "........", + "...43...", + "........", + "........")); + + var innerLoop2 = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "........", + "...12...", + "........", + "........", + "...43...")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop, + innerLoop2 + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(1, result.Length); + Assert.AreEqual(4.0, bottom); + CollectionAssert.AreEquivalent(new[] { 5.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopInnerLoopOnBorderBottom_ReturnsTwoLayers() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + ".4....3.", + "........")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "........", + "...12...", + "........", + "...43...", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(2, result.Length); + Assert.AreEqual(3.0, bottom); + CollectionAssert.AreEquivalent(new[] { 5.0, 1.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopInnerLoopOverlapTop_ReturnsOneLayer() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "..1..2..", + "........", + "........", + ".4....3.", + "........")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "...43...", + "........", + "...12...", + "........", + "........", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(1, result.Length); + Assert.AreEqual(1.0, bottom); + CollectionAssert.AreEquivalent(new[] { 3.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopInnerLoopOnBorderTop_ReturnsOneLayer() + { + // Setup + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + ".4....3.", + "........")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "...43...", + "........", + "...12...", + "........", + "........", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop + } + }; + + // Call + double bottom; + var result = layer.AsPipingSoilLayers(3.5, out bottom).ToArray(); + + // Assert + Assert.AreEqual(1, result.Length); + Assert.AreEqual(1.0, bottom); + CollectionAssert.AreEquivalent(new[] { 3.0 }, result.Select(rl => rl.Top)); + } + + [Test] + public void AsPipingSoilLayers_OuterLoopVerticalAtX_ThrowsException() + { + // Setup + var atX = 2.0; + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + "........", + "..4..3..")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop + }; + + // Call + double bottom; + TestDelegate test = () => layer.AsPipingSoilLayers(atX, out bottom); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(String.Format(Resources.Error_CanNotDetermine1DProfileWithVerticalSegmentsAtX, atX), exception.Message); + } + + [Test] + public void AsPipingSoilLayers_InnerLoopVerticalAtX_ThrowsException() + { + // Setup + var atX = 3.0; + var outerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "..1..2..", + "........", + "........", + "........", + "........", + "..4..3..")); + + var innerLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "6", + "........", + "...1.2..", + "........", + "........", + "...4.3..", + "........")); + + var layer = new SoilLayer2D + { + OuterLoop = outerLoop, + InnerLoops = + { + innerLoop + } + }; + + // Call + double bottom; + TestDelegate test = () => layer.AsPipingSoilLayers(atX, out bottom); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(String.Format(Resources.Error_CanNotDetermine1DProfileWithVerticalSegmentsAtX, atX), exception.Message); + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Builders/SoilProfileBuilderTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Builders/SoilProfileBuilderTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Builders/SoilProfileBuilderTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Wti.Data; +using Wti.Data.TestUtil; +using Wti.IO.Builders; +using Wti.IO.Properties; + +namespace Wti.IO.Test.Builders +{ + public class SoilProfileBuilderTest + { + [Test] + [TestCase(null)] + [TestCase("name")] + public void Constructor_WithNameInvalidX_ThrowsArgumentExcpetion(string name) + { + // Call + TestDelegate test = () => new SoilProfileBuilder(name, double.NaN); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(Resources.Error_SoilProfileBuilderCantDetermineIntersectAtDoubleNaN, exception.Message); + } + + [Test] + [TestCase(null)] + [TestCase("name")] + public void Constructor_WithNameValidX_ReturnsNewInstance(string name) + { + // Call + var builder = new SoilProfileBuilder(name, 0.0); + + // Assert + Assert.NotNull(builder); + } + + [Test] + public void Build_WithOutLayers_ThrowsArgumentException() + { + // Setup + var profileName = "SomeProfile"; + var builder = new SoilProfileBuilder(profileName, 0.0); + + // Call + TestDelegate test = () => builder.Build(); + + // Assert + Assert.Throws(test); + } + + [Test] + public void Build_WithSingleLayerOnlyOuterLoop_ReturnsProfileWithBottomAndALayer() + { + // Setup + var profileName = "SomeProfile"; + var builder = new SoilProfileBuilder(profileName, 0.0); + builder.Add(new SoilLayer2D + { + OuterLoop = new HashSet + { + new Point3D + { + X = -0.5, Z = 1.0 + }, + new Point3D + { + X = 0.5, Z = 1.0 + }, + new Point3D + { + X = 0.5, Z = -1.0 + }, + new Point3D + { + X = -0.5, Z = -1.0 + } + } + }); + + // Call + PipingSoilProfile soilProfile = builder.Build(); + + // Assert + Assert.AreEqual(profileName, soilProfile.Name); + Assert.AreEqual(1, soilProfile.Layers.Count()); + Assert.AreEqual(1.0, soilProfile.Layers.ToArray()[0].Top); + Assert.AreEqual(-1.0, soilProfile.Bottom); + } + + [Test] + public void Build_WithMultipleLayersOnlyOuterLoop_ReturnsProfileWithBottomAndALayers() + { + // Setup + var profileName = "SomeProfile"; + var builder = new SoilProfileBuilder(profileName, 1.0); + builder.Add(new SoilLayer2D + { + OuterLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "10", + "...", + "...", + "...", + "...", + "...", + "...", + "...", + "1.2", + "4.3", + "..." + )) + }).Add(new SoilLayer2D + { + OuterLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "10", + "...", + "...", + "...", + "...", + "...", + "4.3", + "...", + "1.2", + "...", + "..." + )) + }).Add(new SoilLayer2D + { + OuterLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "10", + "...", + "1.2", + "...", + "...", + "...", + "4.3", + "...", + "...", + "...", + "..." + )) + }); + + // Call + PipingSoilProfile soilProfile = builder.Build(); + + // Assert + Assert.AreEqual(profileName, soilProfile.Name); + Assert.AreEqual(3, soilProfile.Layers.Count()); + CollectionAssert.AreEquivalent(new[] { 2.0, 4.0, 8.0 }, soilProfile.Layers.Select(rl => rl.Top)); + Assert.AreEqual(1.0, soilProfile.Bottom); + } + + + [Test] + public void Build_WithLayerFilledWithOtherLayer_ReturnsProfileWithBottomAndALayers() + { + // Setup + var profileName = "SomeProfile"; + var builder = new SoilProfileBuilder(profileName, 2.0); + var loopHole = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "5", + ".....", + ".4.1.", + ".3.2.", + ".....", + "....." + )); + builder.Add(new SoilLayer2D + { + OuterLoop = PointCollectionHelper.CreateFromString(String.Join(Environment.NewLine, + "5", + "2...3", + ".....", + ".....", + ".....", + "1...4" + )), + InnerLoops = + { + loopHole + } + }).Add(new SoilLayer2D + { + OuterLoop = loopHole + }); + + // Call + PipingSoilProfile soilProfile = builder.Build(); + + // Assert + Assert.AreEqual(profileName, soilProfile.Name); + Assert.AreEqual(3, soilProfile.Layers.Count()); + CollectionAssert.AreEquivalent(new[] { 4.0, 3.0, 2.0 }, soilProfile.Layers.Select(rl => rl.Top)); + Assert.AreEqual(0.0, soilProfile.Bottom); + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Calculation/Math2DTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Calculation/Math2DTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Calculation/Math2DTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,186 @@ +using NUnit.Framework; +using Wti.IO.Calculation; + +namespace Wti.IO.Test.Calculation +{ + public class Math2DTest + { + private static readonly double[][] IntersectingSegments = + { + // \/ + // /\ + new[] + { + 0.0, + 0.0, + 1.0, + 1.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.5, + 0.5 + }, + // __ + // / + // / + new[] + { + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0 + }, + // + // / + // /__ + new[] + { + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0 + } + }; + + private static readonly double[][] ParallelSegments = + { + // __ + // __ + new[] + { + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 1.0, + 1.0 + }, + // ____ (connected in single point) + new[] + { + 0.0, + 0.0, + 1.0, + 0.0, + 1.0, + 0.0, + 2.0, + 0.0 + }, + // __ (overlap) + new[] + { + 0.0, + 0.0, + 1.0, + 0.0, + 0.5, + 0.0, + 1.5, + 0.0 + } + }; + + private static readonly double[][] NonIntersectingSegments = + { + // | + // ___ + new[] + { + 0.0, + 0.0, + 1.0, + 0.0, + 0.5, + 1.0, + 0.5, + 0.5 + } + }; + + [Test] + [TestCaseSource("IntersectingSegments")] + public void LineSegmentIntersectionWithLineSegment_DifferentLineSegmentsWithIntersections_ReturnsPoint(double[] coordinates) + { + // Setup + var segments = ToSegmentCoordinatesCollections(coordinates); + + // Call + var result = Math2D.LineSegmentIntersectionWithLineSegment(segments[0], segments[1]); + + // Assert + CollectionAssert.AreEqual(new[] + { + coordinates[8], + coordinates[9] + }, result); + } + + [Test] + [TestCaseSource("ParallelSegments")] + public void LineSegmentIntersectionWithLineSegment_DifferentParallelLineSegments_ReturnsNoPoint(double[] coordinates) + { + // Setup + var segments = ToSegmentCoordinatesCollections(coordinates); + + // Call + var result = Math2D.LineSegmentIntersectionWithLineSegment(segments[0], segments[1]); + + // Assert + Assert.AreEqual(0, result.Length); + } + + [Test] + [TestCaseSource("NonIntersectingSegments")] + public void LineSegmentIntersectionWithLineSegment_DifferentLineSegmentsWithNoIntersection_ReturnsNoPoint(double[] coordinates) + { + // Setup + var segments = ToSegmentCoordinatesCollections(coordinates); + + // Call + var result = Math2D.LineSegmentIntersectionWithLineSegment(segments[0], segments[1]); + + // Assert + Assert.AreEqual(0, result.Length); + } + + private double[][] ToSegmentCoordinatesCollections(double[] coordinates) + { + double[] segmentX = + { + coordinates[0], + coordinates[2], + coordinates[4], + coordinates[6] + }; + double[] segmentY = + { + coordinates[1], + coordinates[3], + coordinates[5], + coordinates[7] + }; + return new[] + { + segmentX, + segmentY + }; + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/CriticalFileReadExceptionTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/CriticalFileReadExceptionTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/CriticalFileReadExceptionTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,72 @@ +using System; + +using NUnit.Framework; + +using Wti.IO.Exceptions; + +namespace Wti.IO.Test.Exceptions +{ + [TestFixture] + public class CriticalFileReadExceptionTest + { + [Test] + [SetCulture("en-US")] + public void DefaultConstructor_ExpectedValues() + { + // Call + var exception = new CriticalFileReadException(); + + // Assert + Assert.IsInstanceOf(exception); + var expectedMessage = string.Format("Exception of type '{0}' was thrown.", exception.GetType()); + Assert.AreEqual(expectedMessage, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.IsNull(exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + + [Test] + public void MessageConstructor_ExpectedValues() + { + // Setup + const string messageText = ""; + + // Call + var exception = new CriticalFileReadException(messageText); + + // Assert + Assert.IsInstanceOf(exception); + Assert.AreEqual(messageText, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.IsNull(exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + + [Test] + public void MessageAndInnerExceptionConstructor_ExpectedValues() + { + // Setup + var innerException = new Exception(); + const string messageText = ""; + + // Call + var exception = new CriticalFileReadException(messageText, innerException); + + // Assert + Assert.IsInstanceOf(exception); + Assert.AreEqual(messageText, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.AreEqual(innerException, exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/LineParseExceptionTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/LineParseExceptionTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/LineParseExceptionTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,72 @@ +using System; + +using NUnit.Framework; + +using Wti.IO.Exceptions; + +namespace Wti.IO.Test.Exceptions +{ + [TestFixture] + public class LineParseExceptionTest + { + [Test] + [SetCulture("en-US")] + public void DefaultConstructor_ExpectedValues() + { + // Call + var exception = new LineParseException(); + + // Assert + Assert.IsInstanceOf(exception); + var expectedMessage = string.Format("Exception of type '{0}' was thrown.", exception.GetType()); + Assert.AreEqual(expectedMessage, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.IsNull(exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + + [Test] + public void MessageConstructor_ExpectedValues() + { + // Setup + const string messageText = ""; + + // Call + var exception = new LineParseException(messageText); + + // Assert + Assert.IsInstanceOf(exception); + Assert.AreEqual(messageText, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.IsNull(exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + + [Test] + public void MessageAndInnerExceptionConstructor_ExpectedValues() + { + // Setup + var innerException = new Exception(); + const string messageText = ""; + + // Call + var exception = new LineParseException(messageText, innerException); + + // Assert + Assert.IsInstanceOf(exception); + Assert.AreEqual(messageText, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.AreEqual(innerException, exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/PipingSoilProfileReadExceptionTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/PipingSoilProfileReadExceptionTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Exceptions/PipingSoilProfileReadExceptionTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,52 @@ +using System; +using NUnit.Framework; +using Wti.IO.Exceptions; + +namespace Wti.IO.Test.Exceptions +{ + public class PipingSoilProfileReadExceptionTest + { + [Test] + public void DefaultConstructor_InnerExceptionNullAndMessageDefault() + { + // Setup + var expectedMessage = String.Format("Exception of type '{0}' was thrown.", typeof(PipingSoilProfileReadException).FullName); + + // Call + var exception = new PipingSoilProfileReadException(); + + // Assert + Assert.IsNull(exception.InnerException); + Assert.AreEqual(expectedMessage, exception.Message); + } + + [Test] + public void Constructor_WithCustomMessage_InnerExceptionNullAndMessageSetToCustom() + { + // Setup + var expectedMessage ="Some exception message"; + + // Call + var exception = new PipingSoilProfileReadException(expectedMessage); + + // Assert + Assert.IsNull(exception.InnerException); + Assert.AreEqual(expectedMessage, exception.Message); + } + + [Test] + public void Constructor_WithCustomMessageAndInnerException_InnerExceptionSetAndMessageSetToCustom() + { + // Setup + var expectedMessage = "Some exception message"; + var expectedInnerException = new Exception(); + + // Call + var exception = new PipingSoilProfileReadException(expectedMessage, expectedInnerException); + + // Assert + Assert.AreSame(expectedInnerException, exception.InnerException); + Assert.AreEqual(expectedMessage, exception.Message); + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilLayerReaderTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilLayerReaderTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilLayerReaderTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,184 @@ +using System.Collections.Generic; +using System.Xml; +using NUnit.Framework; +using Wti.Data; + +namespace Wti.IO.Test +{ + public class PipingSoilLayerReaderTest + { + [Test] + [TestCase(0)] + [TestCase(1)] + public void Constructor_AnyByteArray_ReturnsNewInstance(int size) + { + // Call + var result = new PipingSoilLayer2DReader(new byte[size]); + + // Assert + Assert.NotNull(result); + } + + [Test] + public void Read_MalformedXmlDocument_ThrowsXmlException() + { + // Setup + var xmlDoc = GetBytes("test"); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + TestDelegate test = () => reader.Read(); + + // Assert + Assert.Throws(test); + } + + [Test] + public void Read_XmlDocumentWithoutSaneContent_ReturnsLayerWithoutOuterLoopAndEmptyInnerLoops() + { + // Setup + var xmlDoc = GetBytes(""); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + Assert.IsNull(result.OuterLoop); + CollectionAssert.IsEmpty(result.InnerLoops); + } + + [Test] + public void Read_XmlDocumentWithEmptyOuterLoop_ReturnsLayerWithEmptyOuterLoop() + { + // Setup + var xmlDoc = GetBytes(""); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + CollectionAssert.IsEmpty(result.OuterLoop); + CollectionAssert.IsEmpty(result.InnerLoops); + } + + [Test] + public void Read_XmlDocumentWithEmptyInnerLoop_ReturnsLayerWithOneEmptyInnerLoop() + { + // Setup + var xmlDoc = GetBytes(""); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + Assert.IsNull(result.OuterLoop); + Assert.AreEqual(1, result.InnerLoops.Count); + CollectionAssert.IsEmpty(result.InnerLoops[0]); + } + + [Test] + public void Read_XmlDocumentWithEmptyInnerLoopAndOuterLoop_ReturnsLayerWithEmptyInnerLoopAndEmptyOuterLoop() + { + // Setup + var xmlDoc = GetBytes(""); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + CollectionAssert.IsEmpty(result.OuterLoop); + Assert.AreEqual(1, result.InnerLoops.Count); + CollectionAssert.IsEmpty(result.InnerLoops[0]); + } + + [Test] + [SetCulture("nl-NL")] + public void Read_NLXmlDocumentPointInOuterLoop_ReturnsLayerWithOuterLoopWithPoint() + { + Read_XmlDocumentPointInOuterLoop_ReturnsLayerWithOuterLoopWithPoint(); + } + + [Test] + [SetCulture("en-US")] + public void Read_ENXmlDocumentPointInOuterLoop_ReturnsLayerWithOuterLoopWithPoint() + { + Read_XmlDocumentPointInOuterLoop_ReturnsLayerWithOuterLoopWithPoint(); + } + + private void Read_XmlDocumentPointInOuterLoop_ReturnsLayerWithOuterLoopWithPoint() + { + // Setup + var xmlDoc = GetBytes("00.11.1"); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + CollectionAssert.AreEqual(new HashSet {new Point3D{X=0,Y=0.1,Z=1.1}}, result.OuterLoop); + } + + [Test] + public void Read_XmlDocumentPointInInnerLoop_ReturnsLayerWithInnerLoopWithPoint() + { + // Setup + var xmlDoc = GetBytes("00.11.1"); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + Assert.AreEqual(1, result.InnerLoops.Count); + CollectionAssert.AreEqual(new HashSet { new Point3D { X = 0, Y = 0.1, Z = 1.1 } }, result.InnerLoops[0]); + } + + [Test] + public void Read_XmlDocumentPointsInOuterLoop_ReturnsLayerWithOuterLoopWithPoints() + { + // Setup + var xmlDoc = GetBytes("00.11.110.11.1"); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + CollectionAssert.AreEqual(new HashSet { new Point3D { X = 0, Y = 0.1, Z = 1.1 }, new Point3D { X = 1.0, Y = 0.1, Z = 1.1 } }, result.OuterLoop); + } + + [Test] + public void Read_XmlDocumentPointsInInnerLoop_ReturnsLayerWithInnerLoopWithPoints() + { + // Setup + var xmlDoc = GetBytes("00.11.110.11.1"); + var reader = new PipingSoilLayer2DReader(xmlDoc); + + // Call + var result = reader.Read(); + + // Assert + Assert.NotNull(result); + Assert.AreEqual(1, result.InnerLoops.Count); + CollectionAssert.AreEqual(new HashSet { new Point3D { X = 0, Y = 0.1, Z = 1.1 }, new Point3D { X = 1.0, Y = 0.1, Z = 1.1 } }, result.InnerLoops[0]); + } + + static byte[] GetBytes(string str) + { + byte[] bytes = new byte[str.Length * sizeof(char)]; + System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); + return bytes; + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilProfileReaderTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilProfileReaderTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilProfileReaderTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using DelftTools.TestUtils; +using log4net.Core; +using NUnit.Framework; +using Wti.Data; +using Wti.IO.Calculation; +using Wti.IO.Exceptions; +using Wti.IO.Properties; + +namespace Wti.IO.Test +{ + public class PipingSoilProfileReaderTest + { + + private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Plugins.Wti.WtiIOPath, "PipingSoilProfilesReader"); + + [Test] + public void Constructor_CorrectPath_ReturnsNewInstance() + { + // Setup + var testFile = "empty.soil"; + + // Call + var pipingSoilProfilesReader = new PipingSoilProfileReader(Path.Combine(testDataPath, testFile)); + + // Assert + Assert.NotNull(pipingSoilProfilesReader); + } + + [Test] + public void Constructor_NonExistingPath_ThrowsFileNotFoundException() + { + // Setup + var testFile = Path.Combine(testDataPath, "none.soil"); + + // Call + TestDelegate test = () => new PipingSoilProfileReader(testFile); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(String.Format(Resources.Error_File_0_does_not_exist, testFile), exception.Message); + } + + [Test] + [TestCase(null)] + [TestCase("")] + public void ReadSoilProfiles_NullOrEmpty_ThrowsArgumentException(string fileName) + { + // Call + TestDelegate test = () => new PipingSoilProfileReader(fileName); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(Resources.Error_PathMustBeSpecified, exception.Message); + } + + [Test] + public void ReadSoilProfiles_IncorrectFormatFile_ThrowsSqLiteException() + { + // Setup + var dbName = "text"; + var testFile = Path.Combine(testDataPath, dbName + ".txt"); + var pipingSoilProfilesReader = new PipingSoilProfileReader(testFile); + + // Call + TestDelegate test = () => pipingSoilProfilesReader.Read(); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(String.Format(Resources.Error_SoilProfileReadFromDatabase, dbName), exception.Message); + } + + [Test] + [SetCulture("nl-NL")] + public void ReadSoilProfiles_NLCompleteDatabase_Returns2ProfilesWithLayersAndGeometries() + { + ReadSoilProfiles_CompleteDatabase_Returns2ProfilesWithLayersAndGeometries(); + } + + [Test] + [SetCulture("en-US")] + public void ReadSoilProfiles_ENCompleteDatabase_Returns2ProfilesWithLayersAndGeometries() + { + ReadSoilProfiles_CompleteDatabase_Returns2ProfilesWithLayersAndGeometries(); + } + + private void ReadSoilProfiles_CompleteDatabase_Returns2ProfilesWithLayersAndGeometries() + { + // Setup + var testFile = "complete.soil"; + var pipingSoilProfilesReader = new PipingSoilProfileReader(Path.Combine(testDataPath, testFile)); + + // Call + PipingSoilProfile[] result = pipingSoilProfilesReader.Read().ToArray(); + + // Assert + Assert.AreEqual(2, result.Length); + var firstProfile = result.SingleOrDefault(psp => psp.Name == "10Y_005_STBI"); + Assert.NotNull(firstProfile); + + Assert.AreEqual(-10, firstProfile.Bottom); + Assert.AreEqual(6, firstProfile.Layers.Count()); + var expected = new[] + { + -3.5, + -1.2, + 0.63, + 1.088434916, + 1.947578092, + 2.473341176 + }; + CollectionAssert.AllItemsAreUnique(firstProfile.Layers.Select(l => l.Top)); + Assert.AreEqual(6, firstProfile.Layers.Count(l => expected.Contains(l.Top, new DoubleComparer()))); + } + } + + internal class DoubleComparer : IEqualityComparer { + public bool Equals(double x, double y) + { + return Math.Abs(x - y) < Math2D.EpsilonForComparisons; + } + + public int GetHashCode(double obj) + { + return obj.GetHashCode(); + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSurfaceLinesCsvReaderTest.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSurfaceLinesCsvReaderTest.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSurfaceLinesCsvReaderTest.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,569 @@ +using System; +using System.IO; +using System.Linq; + +using DelftTools.TestUtils; + +using NUnit.Framework; + +using Wti.IO.Exceptions; + +using IOResources = Wti.IO.Properties.Resources; + +namespace Wti.IO.Test +{ + [TestFixture] + public class PipingSurfaceLinesCsvReaderTest + { + private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Plugins.Wti.WtiIOPath, "PipingSurfaceLinesCsvReader" + Path.DirectorySeparatorChar); + + [Test] + [TestCase("")] + [TestCase(null)] + [TestCase(" ")] + public void ParameterdConstructor_InvalidStringArgument_ThrowsArgumentException(string path) + { + // Call + TestDelegate call = () => new PipingSurfaceLinesCsvReader(path); + + // Assert + var exception = Assert.Throws(call); + Assert.AreEqual(IOResources.Error_PathMustBeSpecified, exception.Message); + } + + [Test] + public void ParameterdConstructor_InvalidPathCharactersInPath_ThrowsArgumentException() + { + // Setup + string path = Path.Combine(testDataPath, "TwoValidSurfaceLines.csv"); + + var invalidCharacters = Path.GetInvalidPathChars(); + + var corruptPath = path.Replace('V', invalidCharacters[0]); + + // Call + TestDelegate call = () => new PipingSurfaceLinesCsvReader(corruptPath); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = String.Format(IOResources.Error_PathCannotContainCharacters_0_, + String.Join(", ", Path.GetInvalidFileNameChars())); + Assert.AreEqual(expectedMessage, exception.Message); + } + + [Test] + public void ParametersConstructor_PathToFolder_ThrowsArgumentException() + { + // Call + TestDelegate call = () => new PipingSurfaceLinesCsvReader(testDataPath); + + // Assert + var exception = Assert.Throws(call); + Assert.AreEqual(IOResources.Error_PathMustNotPointToFolder, exception.Message); + } + + [Test] + public void ParameterdConstructor_AnyPath_ExpectedValues() + { + // Setup + const string fakeFilePath = @"I\Dont\Really\Exist"; + + // Call + using (var reader = new PipingSurfaceLinesCsvReader(fakeFilePath)) + { + // Assert + Assert.IsInstanceOf(reader); + } + } + + [Test] + public void GetSurfaceLinesCount_OpenedValidFileWithHeaderAndTwoSurfaceLines_ReturnNumberOfSurfaceLines() + { + // Setup + string path = Path.Combine(testDataPath, "TwoValidSurfaceLines.csv"); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + int linesCount = reader.GetSurfaceLinesCount(); + + // Assert + Assert.AreEqual(2, linesCount); + } + } + + [Test] + public void GetSurfaceLinesCount_OpenedValidFileWithHeaderAndNoSurfaceLines_ReturnZero() + { + // Setup + string path = Path.Combine(testDataPath, "ValidFileWithoutSurfaceLines.csv"); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + int linesCount = reader.GetSurfaceLinesCount(); + + // Assert + Assert.AreEqual(0, linesCount); + } + } + + [Test] + public void GetSurfaceLinesCount_FileCannotBeFound_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "I_do_not_exist.csv"); + + // Precondition + Assert.IsFalse(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.GetSurfaceLinesCount(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_File_0_does_not_exist, path); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + } + + [Test] + public void GetSurfaceLinesCount_DirectoryCannotBeFound_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "..", "this_folder_does_not_exist", "I_do_not_exist.csv"); + + // Precondition + Assert.IsFalse(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.GetSurfaceLinesCount(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_Directory_in_path_0_missing, path); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + } + + [Test] + public void GetSurfaceLinesCount_EmptyFile_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "empty.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.GetSurfaceLinesCount(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_File_0_empty, path); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + public void GetSurfaceLinesCount_InvalidHeader1_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "InvalidHeader_UnsupportedId.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.GetSurfaceLinesCount(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_File_0_invalid_header, path); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + [TestCase("X")] + [TestCase("Y")] + [TestCase("Z")] + public void GetSurfaceLinesCount_InvalidHeader2_ThrowCriticalFileReadException(string missingVariableName) + { + // Setup + var filename = string.Format("InvalidHeader_Lacks{0}1.csv", missingVariableName); + string path = Path.Combine(testDataPath, filename); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.GetSurfaceLinesCount(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format("Het bestand op '{0}' is niet geschikt om dwarsdoorsneden uit te lezen (Verwachte header: locationid;X1;Y1;Z1).", path); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + [SetCulture("nl-NL")] + public void ReadLine_OpenedValidFileWithHeaderAndTwoSurfaceLinesWithCultureNL_ReturnCreatedSurfaceLine() + { + DoReadLine_OpenedValidFileWithHeaderAndTwoSurfaceLines_ReturnCreatedSurfaceLine(); + } + + [Test] + [SetCulture("en-US")] + public void ReadLine_OpenedValidFileWithHeaderAndTwoSurfaceLinesWithCultureEN_ReturnCreatedSurfaceLine() + { + DoReadLine_OpenedValidFileWithHeaderAndTwoSurfaceLines_ReturnCreatedSurfaceLine(); + } + + [Test] + public void ReadLine_OpenedValidFileWithoutHeaderAndTwoSurfaceLinesWhileAtTheEndOfFile_ReturnNull() + { + // Setup + string path = Path.Combine(testDataPath, "TwoValidSurfaceLines.csv"); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + int surfaceLinesCount = reader.GetSurfaceLinesCount(); + for (int i = 0; i < surfaceLinesCount; i++) + { + var pipingSurfaceLine = reader.ReadLine(); + Assert.IsNotInstanceOf(pipingSurfaceLine, + "Fail Fast: Disposal logic required to be implemented in test."); + Assert.IsNotNull(pipingSurfaceLine); + } + + // Call + var result = reader.ReadLine(); + + // Assert + Assert.IsNull(result); + } + } + + [Test] + public void ReadLine_FileCannotBeFound_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "I_do_not_exist.csv"); + + // Precondition + Assert.IsFalse(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_File_0_does_not_exist, path); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + } + + [Test] + public void ReadLine_DirectoryCannotBeFound_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "..", "this_folder_does_not_exist", "I_do_not_exist.csv"); + + // Precondition + Assert.IsFalse(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_Directory_in_path_0_missing, path); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + } + + [Test] + public void ReadLine_EmptyFile_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "empty.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_File_0_empty, path); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + public void ReadLine_InvalidHeader1_ThrowCriticalFileReadException() + { + // Setup + string path = Path.Combine(testDataPath, "InvalidHeader_UnsupportedId.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_File_0_invalid_header, path); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + [TestCase("X")] + [TestCase("Y")] + [TestCase("Z")] + public void ReadLine_InvalidHeader2_ThrowCriticalFileReadException(string missingVariableName) + { + // Setup + var filename = string.Format("InvalidHeader_Lacks{0}1.csv", missingVariableName); + string path = Path.Combine(testDataPath, filename); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format("Het bestand op '{0}' is niet geschikt om dwarsdoorsneden uit te lezen (Verwachte header: locationid;X1;Y1;Z1).", path); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + [TestCase("X")] + [TestCase("Y")] + [TestCase("Z")] + public void ReadLine_FileHasInvalidCoordinate_ThrowLineParseException(string malformattedVariableName) + { + // Setup + string path = Path.Combine(testDataPath, string.Format("InvalidRow_{0}NotAValidNumber.csv", malformattedVariableName)); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_File_0_has_not_double_Line_1_, path, 2); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + } + + [Test] + [TestCase("XOver")] + [TestCase("YOver")] + [TestCase("ZOver")] + [TestCase("XUnder")] + [TestCase("YUnder")] + [TestCase("ZUnder")] + public void ReadLine_FileHasCoordinateCausingOverOrUnderflow_ThrowLineParseException(string malformattedVariableName) + { + // Setup + string path = Path.Combine(testDataPath, string.Format("InvalidRow_{0}flowingNumber.csv", malformattedVariableName)); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.Error_File_0_Parsing_causes_overflow_Line_1_, path, 2); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + } + + [Test] + public void ReadLine_FileLacksIds_ThrowLineParseException() + { + // Setup + string path = Path.Combine(testDataPath, "TwoInvalidRows_LacksId.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + // 1st line has no text at all: + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId, path, 2); + Assert.AreEqual(expectedMessage, exception.Message); + + // 2nd line has only whitespace text: + expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId, path, 3); + exception = Assert.Throws(call); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + public void ReadLine_IncorrectValueSeparator_ThrowLineParseException() + { + // Setup + string path = Path.Combine(testDataPath, "InvalidRow_IncorrectValueSeparator.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_, path, 2, ';'); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + public void ReadLine_FileLacksCoordinateValues_ThrowLineParseException() + { + // Setup + string path = Path.Combine(testDataPath, "InvalidRow_LacksCoordinateValues.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_, path, 2, ';'); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + [Test] + public void ReadLine_FileHasIncompleteCoordinateTriplets_ThrowLineParseException() + { + // Setup + string path = Path.Combine(testDataPath, "TwoInvalidRows_IncompleteCoordinateTriplets.csv"); + + // Precondition + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + TestDelegate call = () => reader.ReadLine(); + + // Assert + // 1st row lacks 1 coordinate value: + var exception = Assert.Throws(call); + var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet, path, 2); + Assert.AreEqual(expectedMessage, exception.Message); + + // 2nd row lacks 2 coordinate values: + exception = Assert.Throws(call); + expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet, path, 3); + Assert.AreEqual(expectedMessage, exception.Message); + } + } + + private void DoReadLine_OpenedValidFileWithHeaderAndTwoSurfaceLines_ReturnCreatedSurfaceLine() + { + // Setup + string path = Path.Combine(testDataPath, "TwoValidSurfaceLines.csv"); + + // Precondition: + Assert.IsTrue(File.Exists(path)); + + using (var reader = new PipingSurfaceLinesCsvReader(path)) + { + // Call + var surfaceLine1 = reader.ReadLine(); + var surfaceLine2 = reader.ReadLine(); + + // Assert + + #region 1st surfaceline + + Assert.AreEqual("Rotterdam1", surfaceLine1.Name); + Assert.AreEqual(8, surfaceLine1.Points.Count()); + Assert.AreEqual(94263.0026213, surfaceLine1.StartingWorldPoint.X); + Assert.AreEqual(427776.654093, surfaceLine1.StartingWorldPoint.Y); + Assert.AreEqual(-1.02, surfaceLine1.StartingWorldPoint.Z); + Assert.AreEqual(94331.1767309, surfaceLine1.EndingWorldPoint.X); + Assert.AreEqual(427960.112661, surfaceLine1.EndingWorldPoint.Y); + Assert.AreEqual(1.44, surfaceLine1.EndingWorldPoint.Z); + Assert.AreEqual(surfaceLine1.StartingWorldPoint, surfaceLine1.Points.First()); + Assert.AreEqual(surfaceLine1.EndingWorldPoint, surfaceLine1.Points.Last()); + + #endregion + + #region 2nd surfaceline + + Assert.AreEqual("ArtificalLocal", surfaceLine2.Name); + Assert.AreEqual(3, surfaceLine2.Points.Count()); + Assert.AreEqual(2.3, surfaceLine2.StartingWorldPoint.X); + Assert.AreEqual(0, surfaceLine2.StartingWorldPoint.Y); + Assert.AreEqual(1, surfaceLine2.StartingWorldPoint.Z); + Assert.AreEqual(4.4, surfaceLine2.EndingWorldPoint.X); + Assert.AreEqual(0, surfaceLine2.EndingWorldPoint.Y); + Assert.AreEqual(1.1, surfaceLine2.EndingWorldPoint.Z); + Assert.AreEqual(surfaceLine2.StartingWorldPoint, surfaceLine2.Points.First()); + Assert.AreEqual(surfaceLine2.EndingWorldPoint, surfaceLine2.Points.Last()); + + #endregion + } + } + } +} \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Properties/AssemblyInfo.cs =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Properties/AssemblyInfo.cs (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Properties/AssemblyInfo.cs (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,39 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Wti.IO.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Wti.IO.Test")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("fdd7359e-075c-49b6-b792-056e46a28a57")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Wti.IO.Test.csproj =================================================================== diff -u --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Wti.IO.Test.csproj (revision 0) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/Wti.IO.Test.csproj (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {E4B0E068-F1A3-47BA-965F-0EC1E78E530A} + Library + Properties + Wti.IO.Test + Wti.IO.Test + v4.0 + 512 + + + true + bin\Debug\ + 4 + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\Release\ + 4 + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\..\..\..\lib\log4net.dll + + + ..\..\..\..\..\..\lib\nunit.framework.dll + + + + + + + + + + + + + + + + + + + + {ce994cc9-6f6a-48ac-b4be-02c30a21f4db} + Wti.Data + + + {EFA25023-CF6A-4FF7-8C42-B24D7F9509E1} + DelftTools.TestUtils + + + {35b87b7a-7f50-4139-b563-589ee522b1ed} + Wti.IO + + + {955E574D-67CE-4347-AA6B-7DF8A04ED754} + Wti.Data.TestUtil + + + + + \ No newline at end of file Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/Ringtoets.Piping.Plugin.Test.csproj =================================================================== diff -u -r1450c6e12cbd3358c66a9efec22203c988af78ed -rb3fa1606efddd3bed496c2844a495ff92347fa44 --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/Ringtoets.Piping.Plugin.Test.csproj (.../Ringtoets.Piping.Plugin.Test.csproj) (revision 1450c6e12cbd3358c66a9efec22203c988af78ed) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/Ringtoets.Piping.Plugin.Test.csproj (.../Ringtoets.Piping.Plugin.Test.csproj) (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -82,10 +82,6 @@ {ce994cc9-6f6a-48ac-b4be-02c30a21f4db} Wti.Data - - {35b87b7a-7f50-4139-b563-589ee522b1ed} - Wti.IO - {efa25023-cf6a-4ff7-8c42-b24d7f9509e1} DelftTools.TestUtils @@ -94,6 +90,10 @@ {7cd038e1-e111-4969-aced-22c5bd2974e1} Wti.Forms + + {35b87b7a-7f50-4139-b563-589ee522b1ed} + Wti.IO + {1d3d58b6-ef7e-401e-92a0-104067d222ee} Ringtoets.Piping.Plugin Index: src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.Service.Test/Ringtoets.Piping.Service.Test.csproj =================================================================== diff -u -r53a2d662c6893cb7e63dc150aaab6c2b3e9db769 -rb3fa1606efddd3bed496c2844a495ff92347fa44 --- src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.Service.Test/Ringtoets.Piping.Service.Test.csproj (.../Ringtoets.Piping.Service.Test.csproj) (revision 53a2d662c6893cb7e63dc150aaab6c2b3e9db769) +++ src/Plugins/Ringtoets/Piping/test/Ringtoets.Piping.Service.Test/Ringtoets.Piping.Service.Test.csproj (.../Ringtoets.Piping.Service.Test.csproj) (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -77,7 +77,7 @@ {CE994CC9-6F6A-48AC-B4BE-02C30A21F4DB} Wti.Data - + {7cd038e1-e111-4969-aced-22c5bd2974e1} Wti.Forms Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Builders/SoilLayer2D.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Builders/SoilLayer2DConversionException.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Builders/SoilProfileBuilder.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Calculation/Math2D.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Exceptions/CriticalFileReadException.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Exceptions/LineParseException.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Exceptions/PipingSoilProfileReadException.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/PipingSoilLayer2DReader.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/PipingSoilProfileReader.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/PipingSurfaceLinesCsvReader.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Properties/AssemblyInfo.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Properties/Resources.Designer.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Properties/Resources.resx'. Fisheye: No comparison available. Pass `N' to diff? Index: src/Plugins/Wti/Wti.IO/SQLite.Interop.dll =================================================================== diff -u -re5c186677d0ef8697eb04ea571b7c4ef8268183c -rb3fa1606efddd3bed496c2844a495ff92347fa44 Binary files differ Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/Wti.IO.csproj'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `src/Plugins/Wti/Wti.IO/packages.config'. Fisheye: No comparison available. Pass `N' to diff? Index: src/documentation/UML/UML.csproj =================================================================== diff -u -r53a2d662c6893cb7e63dc150aaab6c2b3e9db769 -rb3fa1606efddd3bed496c2844a495ff92347fa44 --- src/documentation/UML/UML.csproj (.../UML.csproj) (revision 53a2d662c6893cb7e63dc150aaab6c2b3e9db769) +++ src/documentation/UML/UML.csproj (.../UML.csproj) (revision b3fa1606efddd3bed496c2844a495ff92347fa44) @@ -70,7 +70,7 @@ {ce994cc9-6f6a-48ac-b4be-02c30a21f4db} Wti.Data - + {7cd038e1-e111-4969-aced-22c5bd2974e1} Wti.Forms Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Builders/SoilLayer2DTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Builders/SoilProfileBuilderTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Calculation/Math2DTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Exceptions/CriticalFileReadExceptionTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Exceptions/LineParseExceptionTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Exceptions/PipingSoilProfileReadExceptionTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/PipingSoilLayerReaderTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/PipingSoilProfileReaderTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/PipingSurfaceLinesCsvReaderTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Properties/AssemblyInfo.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag b3fa1606efddd3bed496c2844a495ff92347fa44 refers to a dead (removed) revision in file `test/Plugins/Wti/Wti.IO.Test/Wti.IO.Test.csproj'. Fisheye: No comparison available. Pass `N' to diff?