예제 #1
0
        /// <summary>
        /// Tests whether two <see cref="CoordinateSequence"/>s are equal.
        /// To be equal, the sequences must be the same length.
        /// They do not need to be of the same dimension,
        /// but the ordinate values for the smallest dimension of the two
        /// must be equal.
        /// Two <c>NaN</c> ordinates values are considered to be equal.
        /// </summary>
        /// <param name="cs1">a CoordinateSequence</param>
        /// <param name="cs2">a CoordinateSequence</param>
        /// <returns><c>true</c> if the sequences are equal in the common dimensions</returns>
        public static bool IsEqual(CoordinateSequence cs1, CoordinateSequence cs2)
        {
            int cs1Size = cs1.Count;
            int cs2Size = cs2.Count;

            if (cs1Size != cs2Size)
            {
                return(false);
            }
            int dim = Math.Min(cs1.Dimension, cs2.Dimension);

            for (int i = 0; i < cs1Size; i++)
            {
                for (int d = 0; d < dim; d++)
                {
                    double v1 = cs1.GetOrdinate(i, d);
                    double v2 = cs2.GetOrdinate(i, d);
                    if (cs1.GetOrdinate(i, d) == cs2.GetOrdinate(i, d))
                    {
                        continue;
                    }
                    // special check for NaNs
                    if (double.IsNaN(v1) && double.IsNaN(v2))
                    {
                        continue;
                    }
                    return(false);
                }
            }
            return(true);
        }
예제 #2
0
        /// <summary>
        /// Ensures that a CoordinateSequence forms a valid ring,
        /// returning a new closed sequence of the correct length if required.
        /// If the input sequence is already a valid ring, it is returned
        /// without modification.
        /// If the input sequence is too short or is not closed,
        /// it is extended with one or more copies of the start point.
        /// </summary>
        /// <param name="fact">The CoordinateSequenceFactory to use to create the new sequence</param>
        /// <param name="seq">The sequence to test</param>
        /// <returns>The original sequence, if it was a valid ring, or a new sequence which is valid.</returns>
        public static CoordinateSequence EnsureValidRing(CoordinateSequenceFactory fact, CoordinateSequence seq)
        {
            int n = seq.Count;

            // empty sequence is valid
            if (n == 0)
            {
                return(seq);
            }
            // too short - make a new one
            if (n <= 3)
            {
                return(CreateClosedRing(fact, seq, 4));
            }

            bool isClosed = seq.GetOrdinate(0, 0) == seq.GetOrdinate(n - 1, 0) &&
                            seq.GetOrdinate(0, 1) == seq.GetOrdinate(n - 1, 1);

            if (isClosed)
            {
                return(seq);
            }
            // make a new closed ring
            return(CreateClosedRing(fact, seq, n + 1));
        }
예제 #3
0
 /// <summary>
 /// Returns the index of <c>coordinate</c> in a <see cref="CoordinateSequence"/>
 /// The first position is 0; the second, 1; etc.
 /// </summary>
 /// <param name="coordinate">The <c>Coordinate</c> to search for</param>
 /// <param name="seq">The coordinate sequence to search</param>
 /// <returns>
 /// The position of <c>coordinate</c>, or -1 if it is not found
 /// </returns>
 public static int IndexOf(Coordinate coordinate, CoordinateSequence seq)
 {
     for (int i = 0; i < seq.Count; i++)
     {
         if (coordinate.X == seq.GetOrdinate(i, 0) &&
             coordinate.Y == seq.GetOrdinate(i, 1))
         {
             return(i);
         }
     }
     return(-1);
 }
예제 #4
0
        /// <summary>
        /// Swaps two coordinates in a sequence.
        /// </summary>
        /// <param name="seq">seq the sequence to modify</param>
        /// <param name="i">the index of a coordinate to swap</param>
        /// <param name="j">the index of a coordinate to swap</param>
        public static void Swap(CoordinateSequence seq, int i, int j)
        {
            if (i == j)
            {
                return;
            }

            for (int dim = 0; dim < seq.Dimension; dim++)
            {
                double tmp = seq.GetOrdinate(i, dim);
                seq.SetOrdinate(i, dim, seq.GetOrdinate(j, dim));
                seq.SetOrdinate(j, dim, tmp);
            }
        }
예제 #5
0
        /// <summary>
        /// Shifts the positions of the coordinates until the coordinate at  <code>firstCoordinateIndex</code>
        /// is first.
        /// </summary>
        /// <param name="seq">The coordinate sequence to rearrange</param>
        /// <param name="indexOfFirstCoordinate">The index of the coordinate to make first</param>
        /// <param name="ensureRing">Makes sure that <paramref name="seq"/> will be a closed ring upon exit</param>
        public static void Scroll(CoordinateSequence seq, int indexOfFirstCoordinate, bool ensureRing)
        {
            int i = indexOfFirstCoordinate;

            if (i <= 0)
            {
                return;
            }

            // make a copy of the sequence
            var copy = seq.Copy();

            // test if ring, determine last index
            int last = ensureRing ? seq.Count - 1 : seq.Count;

            // fill in values
            for (int j = 0; j < last; j++)
            {
                for (int k = 0; k < seq.Dimension; k++)
                {
                    seq.SetOrdinate(j, k, copy.GetOrdinate((indexOfFirstCoordinate + j) % last, k));
                }
            }

            // Fix the ring (first == last)
            if (ensureRing)
            {
                for (int k = 0; k < seq.Dimension; k++)
                {
                    seq.SetOrdinate(last, k, seq.GetOrdinate(0, k));
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Creates a string representation of a <see cref="CoordinateSequence"/>.
        /// The format is:
        /// <para>
        ///  ( ord0,ord1.. ord0,ord1,...  ... )
        /// </para>
        /// </summary>
        /// <param name="cs">the sequence to output</param>
        /// <returns>the string representation of the sequence</returns>
        public static string ToString(CoordinateSequence cs)
        {
            int size = cs.Count;

            if (size == 0)
            {
                return("()");
            }
            int dim = cs.Dimension;
            var sb  = new StringBuilder();

            sb.Append('(');
            for (int i = 0; i < size; i++)
            {
                if (i > 0)
                {
                    sb.Append(" ");
                }
                for (int d = 0; d < dim; d++)
                {
                    if (d > 0)
                    {
                        sb.Append(",");
                    }
                    double ordinate = cs.GetOrdinate(i, d);
                    sb.Append(string.Format("{0:0.#}", ordinate));
                }
            }
            sb.Append(')');
            return(sb.ToString());
        }
예제 #7
0
        /// <summary>
        /// Tests whether a <see cref="CoordinateSequence"/> forms a valid <see cref="LinearRing"/>,
        /// by checking the sequence length and closure
        /// (whether the first and last points are identical in 2D).
        /// Self-intersection is not checked.
        /// </summary>
        /// <param name="seq">The sequence to test</param>
        /// <returns>True if the sequence is a ring</returns>
        /// <seealso cref="LinearRing"/>
        public static bool IsRing(CoordinateSequence seq)
        {
            int n = seq.Count;

            if (n == 0)
            {
                return(true);
            }
            // too few points
            if (n <= 3)
            {
                return(false);
            }
            // test if closed
            return(seq.GetOrdinate(0, 0) == seq.GetOrdinate(n - 1, 0) &&
                   seq.GetOrdinate(0, 1) == seq.GetOrdinate(n - 1, 1));
        }
예제 #8
0
        /// <summary>
        /// Copies a coordinate of a <see cref="CoordinateSequence"/> to another <see cref="CoordinateSequence"/>.
        /// The sequences may have different dimensions;
        /// in this case only the common dimensions are copied.
        /// </summary>
        /// <param name="src">The sequence to copy coordinate from</param>
        /// <param name="srcPos">The index of the coordinate to copy</param>
        /// <param name="dest">The sequence to which the coordinate should be copied to</param>
        /// <param name="destPos">The index of the coordinate in <see paramref="dest"/></param>
        public static void CopyCoord(CoordinateSequence src, int srcPos, CoordinateSequence dest, int destPos)
        {
            int minDim = Math.Min(src.Dimension, dest.Dimension);

            for (int dim = 0; dim < minDim; dim++)
            {
                double value = src.GetOrdinate(srcPos, dim);
                dest.SetOrdinate(destPos, dim, value);
            }
        }
예제 #9
0
        /// <summary>
        /// Creates a <see cref="CoordinateSequence" />  which is a copy
        /// of the given <see cref="CoordinateSequence" />.
        /// This method must handle null arguments by creating an empty sequence.
        /// </summary>
        /// <param name="coordSeq"></param>
        /// <returns>A coordinate sequence</returns>
        public virtual CoordinateSequence Create(CoordinateSequence coordSeq)
        {
            var result = Create(coordSeq?.Count ?? 0, coordSeq?.Dimension ?? 2, coordSeq?.Measures ?? 0);

            if (coordSeq != null)
            {
                for (int i = 0; i < coordSeq.Count; i++)
                {
                    for (int dim = 0; dim < result.Dimension; dim++)
                    {
                        result.SetOrdinate(i, dim, coordSeq.GetOrdinate(i, dim));
                    }
                }
            }

            return(result);
        }
예제 #10
0
        public override double[] GetOrdinates(Ordinate ordinate)
        {
            if (IsEmpty)
            {
                return(new double[0]);
            }

            var ordinateFlag = (Ordinates)(1 << (int)ordinate);

            if ((_coordinates.Ordinates & ordinateFlag) != ordinateFlag)
            {
                return new[] { Coordinate.NullOrdinate }
            }
            ;

            double val = _coordinates.TryGetOrdinateIndex(ordinate, out int ordinateIndex)
                ? _coordinates.GetOrdinate(0, ordinateIndex)
                : Coordinate.NullOrdinate;

            return(new[] { val });
        }
예제 #11
0
 public override double GetOrdinate(int index, int ordinateIndex) => _inner.GetOrdinate(Count - index - 1, ordinateIndex);