Index: Ringtoets/Common/src/Ringtoets.Common.IO/SoilProfile/SoilProfile2DReader.cs =================================================================== diff -u -r0fa0d88d03cc6adb9d820c65c4c7a43e853ef5a3 -r7585d2fd78627d94d55ffa16423af90a91e4efd4 --- Ringtoets/Common/src/Ringtoets.Common.IO/SoilProfile/SoilProfile2DReader.cs (.../SoilProfile2DReader.cs) (revision 0fa0d88d03cc6adb9d820c65c4c7a43e853ef5a3) +++ Ringtoets/Common/src/Ringtoets.Common.IO/SoilProfile/SoilProfile2DReader.cs (.../SoilProfile2DReader.cs) (revision 7585d2fd78627d94d55ffa16423af90a91e4efd4) @@ -171,19 +171,19 @@ private SoilProfile2D TryReadSoilProfile() { var criticalProperties = new CriticalProfileProperties(this); - var soilLayers = new List(); + var soilLayerGeometries = new List(); var stresses = new List(); long soilProfileId = criticalProperties.ProfileId; RequiredProfileProperties properties; - + try { properties = new RequiredProfileProperties(this, criticalProperties.ProfileName); for (var i = 1; i <= criticalProperties.LayerCount; i++) { - soilLayers.Add(ReadSoilLayerFrom(this, criticalProperties.ProfileName)); + soilLayerGeometries.Add(ReadSoilLayerGeometryFrom(this, criticalProperties.ProfileName)); MoveNext(); } @@ -199,7 +199,7 @@ { return new SoilProfile2D(soilProfileId, criticalProperties.ProfileName, - soilLayers, + GetSoilLayers(soilLayerGeometries), stresses) { IntersectionX = properties.IntersectionX @@ -232,28 +232,105 @@ return preconsolidationStressReader.ReadPreconsolidationStresses().ToArray(); } + private static IEnumerable GetSoilLayers(List soilLayerGeometries) + { + SoilLayer2DLoop[] innerLoops = soilLayerGeometries.SelectMany(slg => slg.InnerLoops).ToArray(); + + foreach (SoilLayer2DGeometry soilLayerGeometry in soilLayerGeometries) + { + if (IsNestedLayer(innerLoops, soilLayerGeometry)) + { + continue; + } + + SoilLayer2D soilLayer = CreateSoilLayer2D(soilLayerGeometry); + + CreateNestedSoilLayersRecursively(soilLayerGeometries, soilLayerGeometry, soilLayer); + + yield return soilLayer; + } + } + + private static void CreateNestedSoilLayersRecursively(List soilLayerGeometries, SoilLayer2DGeometry soilLayerGeometry, SoilLayer2D soilLayer) + { + var nestedLayers = new List(); + + foreach (SoilLayer2DLoop innerLoop in soilLayerGeometry.InnerLoops) + { + SoilLayer2DGeometry nestedSoilLayerGeometry = soilLayerGeometries.First(slg => slg.OuterLoop.Segments.SequenceEqual(innerLoop.Segments)); + SoilLayer2D nestedSoilLayer = CreateSoilLayer2D(nestedSoilLayerGeometry); + + CreateNestedSoilLayersRecursively(soilLayerGeometries, nestedSoilLayerGeometry, nestedSoilLayer); + + nestedLayers.Add(nestedSoilLayer); + } + + soilLayer.NestedLayers = StripDuplicateNestedLayers(nestedLayers); + } + + private static SoilLayer2D CreateSoilLayer2D(SoilLayer2DGeometry soilLayerGeometry) + { + var soilLayer = new SoilLayer2D(soilLayerGeometry.OuterLoop, soilLayerGeometry.InnerLoops); + + SoilLayerHelper.SetSoilLayerBaseProperties(soilLayer, soilLayerGeometry.LayerProperties); + + return soilLayer; + } + + private static bool IsNestedLayer(IEnumerable innerLoops, SoilLayer2DGeometry soilLayerGeometry) + { + return innerLoops.Any(il => il.Segments.SequenceEqual(soilLayerGeometry.OuterLoop.Segments)); + } + + private static IEnumerable StripDuplicateNestedLayers(List nestedLayers) + { + return nestedLayers.Where(nl => !nestedLayers.Except( + new[] + { + nl + }) + .SelectMany(GetLayersRecursively) + .Any(l => l.OuterLoop.Segments.SequenceEqual(nl.OuterLoop.Segments))); + } + + private static IEnumerable GetLayersRecursively(SoilLayer2D soilLayer) + { + var layers = new List + { + soilLayer + }; + + foreach (SoilLayer2D nestedLayer in soilLayer.NestedLayers) + { + layers.AddRange(GetLayersRecursively(nestedLayer)); + } + + return layers; + } + /// - /// Reads a from the given . + /// Reads a from the given . /// - /// Thrown when reading properties of the layers failed. - private static SoilLayer2D ReadSoilLayerFrom(IRowBasedDatabaseReader reader, string profileName) + /// The reader to read the geometry from. + /// The name of the profile to read the geometry for. + /// A . + /// Thrown when reading properties of the geometry failed. + private static SoilLayer2DGeometry ReadSoilLayerGeometryFrom(IRowBasedDatabaseReader reader, string profileName) { var properties = new Layer2DProperties(reader, profileName); - byte[] geometryValue = properties.GeometryValue; - SoilLayer2D soilLayer; try { - soilLayer = new SoilLayer2DGeometryReader().Read(geometryValue); + SoilLayer2DGeometry soilLayerGeometry = new SoilLayer2DGeometryReader().Read(properties.GeometryValue); + + soilLayerGeometry.LayerProperties = properties; + + return soilLayerGeometry; } catch (SoilLayerConversionException e) { throw CreateSoilProfileReadException(reader.Path, profileName, e); } - - SoilLayerHelper.SetSoilLayerBaseProperties(soilLayer, properties); - - return soilLayer; } private static SoilProfileReadException CreateSoilProfileReadException(string filePath, string profileName, Exception innerException)