// Copyright (C) Stichting Deltares 2016. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Data; using System.IO; using System.Linq; using Core.Common.Base.Geometry; using Core.Common.IO.Exceptions; using Core.Common.Utils; using Core.Common.Utils.Builders; using Core.Components.Gis.Data; using DotSpatial.Data; using CoreCommonUtilsResources = Core.Common.Utils.Properties.Resources; using GisIOResources = Core.Components.Gis.IO.Properties.Resources; namespace Core.Components.Gis.IO { /// /// Class to be used to read polylines from a shapefile. /// public class PolylineShapeFileReader : IDisposable { private readonly string filePath; private readonly LineShapefile lineShapeFile; private int readIndex; /// /// Initializes a new instance of the class. /// /// The shapefile path. /// When is invalid. /// When either: /// /// points to a file that doesn't exist. /// The shapefile has non-line geometries in it. /// public PolylineShapeFileReader(string shapeFilePath) { FileUtils.ValidateFilePath(shapeFilePath); if (!File.Exists(shapeFilePath)) { string message = new FileReaderErrorMessageBuilder(shapeFilePath) .Build(CoreCommonUtilsResources.Error_File_does_not_exist); throw new CriticalFileReadException(message); } filePath = shapeFilePath; try { lineShapeFile = new LineShapefile(shapeFilePath); } catch (ArgumentException e) { string message = new FileReaderErrorMessageBuilder(shapeFilePath) .Build(GisIOResources.LineShapeFileReader_File_contains_geometries_not_line); throw new CriticalFileReadException(message, e); } } /// /// Gets the number of lines in the shapefile. /// public int GetNumberOfLines() { return lineShapeFile.Features.Count; } /// /// Reads a line shape from the file. /// /// The representing the read line shape, or /// null when at the end of the shapefile. /// When reading a multi-line feature. public MapLineData ReadLine(string name = null) { if (readIndex == lineShapeFile.Features.Count) { return null; } try { IFeature lineFeature = GetSingleLineFeature(readIndex); return ConvertSingleLineFeatureToMapLineData(lineFeature, name ?? GisIOResources.PolylineShapeFileReader_ReadLine_Line); } finally { readIndex++; } } /// /// Determines whether the specified attribute has been defined in the shapefile attributes. /// /// Name of the attribute. /// True is the attribute is defined, false otherwise. /// This check is case-sensitive. public bool HasAttribute(string attributeName) { return lineShapeFile.Attributes.Columns.Any(c => c.ColumnName == attributeName); } public void Dispose() { lineShapeFile.Close(); } /// /// Gets the single line feature at the given index. /// /// The index of which feature to retrieve. /// The feature that consists out of 1 whole polyline. /// When reading a multi-line feature. private IFeature GetSingleLineFeature(int index) { IFeature lineFeature = lineShapeFile.Features[index]; if (lineFeature.NumGeometries > 1) { string message = new FileReaderErrorMessageBuilder(filePath) .WithLocation(string.Format(GisIOResources.PolylineShapeFileReader_GetSingleLineFeature_At_shapefile_index_0_, index)) .Build(GisIOResources.PolylineShapeFileReader_ReadLine_Read_unsupported_multipolyline); throw new ElementReadException(message); } return lineFeature; } private MapLineData ConvertSingleLineFeatureToMapLineData(IFeature lineFeature, string name) { var lineData = new MapLineData(lineFeature.Coordinates.Select(c => new Point2D(c.X, c.Y)), name); DataTable table = lineShapeFile.GetAttributes(readIndex, 1); DataRow dataRow = table.Rows[0]; for (int i = 0; i < table.Columns.Count; i++) { lineData.MetaData[table.Columns[i].ColumnName] = dataRow[i]; } return lineData; } } }