/// <summary> /// Gets the three parameters needed to create any <see cref="CoordinateSequence"/> instance /// (<see cref="CoordinateSequence.Count"/>, <see cref="CoordinateSequence.Dimension"/>, and /// <see cref="CoordinateSequence.Measures"/>) such that the sequence can store all the data /// from a given array of <see cref="Coordinate"/> instances. /// </summary> /// <param name="coordinates"> /// The array of <see cref="Coordinate"/> instances that the sequence will be created from. /// </param> /// <returns> /// The values of the three parameters to use for creating the sequence. /// </returns> public static (int Count, int Dimension, int Measures) GetCommonSequenceParameters(Coordinate[] coordinates) { if (coordinates == null) { return(0, 2, 0); } int count = coordinates.Length; int spatial = 2; int measures = 0; // figure out the minimum number of spatial dimensions and measures needed to hold all // the data from the array. this is NOT CoordinateArrays.Dimension(coordinates) and // CoordinateArrays.Measures(coordinates): an array of only CoordinateZ and CoordinateM // instances mixed together will give us dimension = 3 and measures = 1, which would // mean that the resulting sequence would not contain Z. foreach (var coord in coordinates) { int coordDimension = Coordinates.Dimension(coord); int coordMeasures = Coordinates.Measures(coord); int coordSpatial = coordDimension - coordMeasures; if (coordSpatial > spatial) { spatial = coordSpatial; } if (coordMeasures > measures) { measures = coordMeasures; } } return(count, spatial + measures, measures); }
/// <summary> /// Utility method ensuring array contents are of consistent dimension and measures. /// <para/> /// Array is modified in place if required, coordinates are replaced in the array as required /// to ensure all coordinates have the same dimension and measures. The final dimension and /// measures used are the maximum found when checking the array. /// </summary> /// <param name="array">Modified in place to coordinates of consistent dimension and measures.</param> public static void EnforceConsistency(Coordinate[] array) { if (array == null) { return; } // step one check int maxSpatialDimension = -1; int maxMeasures = -1; bool isConsistent = true; for (int i = 0; i < array.Length; i++) { var coordinate = array[i]; if (coordinate != null) { int m = Coordinates.Measures(coordinate); int sd = Coordinates.Dimension(coordinate) - m; if (maxSpatialDimension == -1) { maxMeasures = m; maxSpatialDimension = sd; continue; } if (sd != maxSpatialDimension || m != maxMeasures) { isConsistent = false; maxSpatialDimension = Math.Max(maxSpatialDimension, sd); maxMeasures = Math.Max(maxMeasures, m); } } } if (!isConsistent) { // step two fix int maxDimension = maxSpatialDimension + maxMeasures; var sample = Coordinates.Create(maxDimension, maxMeasures); var type = sample.GetType(); for (int i = 0; i < array.Length; i++) { var coordinate = array[i]; if (coordinate != null && coordinate.GetType() != type) { var duplicate = Coordinates.Create(maxDimension, maxMeasures); duplicate.CoordinateValue = coordinate; array[i] = duplicate; } } } }
/// <summary> /// Determine dimension based on subclass of <see cref="Coordinate"/>. /// </summary> /// <param name="pts">pts supplied coordinates</param> /// <returns>number of ordinates recorded</returns> public static int Dimension(Coordinate[] pts) { if (pts == null || pts.Length == 0) { return(2); // unknown, assume default } int dimension = 0; foreach (var coordinate in pts) { dimension = Math.Max(dimension, Coordinates.Dimension(coordinate)); } return(dimension); }
/// <summary> /// Returns a <see cref="CoordinateSequence" /> based on the given array; /// whether or not the array is copied is implementation-dependent. /// </summary> /// <param name="coordinates">A coordinates array, which may not be null nor contain null elements</param> /// <returns>A coordinate sequence.</returns> public virtual CoordinateSequence Create(Coordinate[] coordinates) { (int count, int dimension, int measures) = GetCommonSequenceParameters(coordinates); var result = Create(count, dimension, measures); if (coordinates != null) { int spatial = dimension - measures; for (int i = 0; i < coordinates.Length; i++) { var coord = coordinates[i]; int coordDimension = Coordinates.Dimension(coord); int coordMeasures = Coordinates.Measures(coord); int coordSpatial = coordDimension - coordMeasures; for (int dim = 0; dim < coordSpatial; dim++) { result.SetOrdinate(i, dim, coord[dim]); } for (int dim = coordSpatial; dim < spatial; dim++) { result.SetOrdinate(i, dim, Coordinate.NullOrdinate); } for (int measure = 0; measure < coordMeasures; measure++) { result.SetOrdinate(i, spatial + measure, coord[coordSpatial + measure]); } for (int measure = coordMeasures; measure < measures; measure++) { result.SetOrdinate(i, spatial + measure, Coordinate.NullOrdinate); } } } return(result); }