// 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.Collections.Generic;
using System.IO;
using System.Linq;
using Core.Common.Base.Geometry;
using Core.Common.IO.Exceptions;
using Core.Common.Utils.Builders;
using Core.Components.Gis.Data;
using Core.Components.Gis.Features;
using Core.Components.Gis.Geometries;
using DotSpatial.Data;
using DotSpatial.Topology;
using CoreCommonUtilsResources = Core.Common.Utils.Properties.Resources;
using GisIOResources = Core.Components.Gis.IO.Properties.Resources;
namespace Core.Components.Gis.IO.Readers
{
///
/// Class to be used to read polylines from a shapefile.
///
public class PolylineShapeFileReader : ShapeFileReaderBase
{
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.
/// - An unexpected error occurred when reading the shapefile.
///
///
public PolylineShapeFileReader(string shapeFilePath) : base(shapeFilePath)
{
try
{
ShapeFile = new LineShapefile(shapeFilePath);
}
catch (ArgumentException exception)
{
string message = new FileReaderErrorMessageBuilder(shapeFilePath)
.Build(GisIOResources.LineShapeFileReader_File_contains_geometries_not_line);
throw new CriticalFileReadException(message, exception);
}
catch (IOException exception)
{
var message = new FileReaderErrorMessageBuilder(shapeFilePath).Build(CoreCommonUtilsResources.Error_General_IO_Import_ErrorMessage);
throw new CriticalFileReadException(message, exception);
}
}
///
/// Reads a line shape from the file.
///
/// The representing the read line shape, or
/// null when at the end of the shapefile.
public override FeatureBasedMapData ReadFeature(string name = null)
{
if (readIndex == GetNumberOfFeatures())
{
return null;
}
try
{
IFeature lineFeature = GetFeature(readIndex);
return ConvertSingleLineFeatureToMapLineData(lineFeature, !string.IsNullOrWhiteSpace(name) ? name : GisIOResources.PolylineShapeFileReader_ReadLine_Line);
}
finally
{
readIndex++;
}
}
public override FeatureBasedMapData ReadShapeFile(string name = null)
{
List featureList = new List();
while (readIndex != GetNumberOfFeatures())
{
featureList.Add(ReadFeatureLine());
}
return ConvertMultiLineFeatureToMapLineData(featureList, !string.IsNullOrWhiteSpace(name) ? name : GisIOResources.PolylineShapeFileReader_ReadLine_Line);
}
///
/// 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.
public override IFeature GetFeature(int index)
{
return ShapeFile.Features[index];
}
private IFeature ReadFeatureLine()
{
try
{
return GetFeature(readIndex);
}
finally
{
readIndex++;
}
}
private MapLineData ConvertSingleLineFeatureToMapLineData(IFeature lineFeature, string name)
{
MapFeature feature = CreateMapFeatureForLineFeature(lineFeature);
CopyMetaDataIntoFeature(feature, readIndex);
return new MapLineData(name)
{
Features = new[]
{
feature
}
};
}
private MapLineData ConvertMultiLineFeatureToMapLineData(List lineFeatures, string name)
{
var mapFeatureList = new List();
for (var featureIndex = 0; featureIndex < lineFeatures.Count; featureIndex++)
{
IFeature lineFeature = lineFeatures[featureIndex];
MapFeature feature = CreateMapFeatureForLineFeature(lineFeature);
CopyMetaDataIntoFeature(feature, featureIndex);
mapFeatureList.Add(feature);
}
return new MapLineData(name)
{
Features = mapFeatureList.ToArray()
};
}
private static MapFeature CreateMapFeatureForLineFeature(IFeature lineFeature)
{
var geometries = new List();
for (int i = 0; i < lineFeature.BasicGeometry.NumGeometries; i++)
{
var polylineGeometry = lineFeature.BasicGeometry.GetBasicGeometryN(i);
MapGeometry mapGeometry = new MapGeometry(GetMapGeometryPointCollections(polylineGeometry.Coordinates));
geometries.Add(mapGeometry);
}
return new MapFeature(geometries);
}
private static IEnumerable[] GetMapGeometryPointCollections(IEnumerable lineCoordinates)
{
return new[]
{
lineCoordinates.Select(c => new Point2D(c.X, c.Y))
};
}
}
}