コード例 #1
0
        private bool CheckSequences(CoordinateSequence c1, CoordinateSequence c2)
        {
            if (c1.Count != c2.Count)
            {
                return(false);
            }
            if (c1.Dimension != c2.Dimension)
            {
                return(false);
            }
            if (c1.Measures != c2.Measures)
            {
                return(false);
            }

            for (int i = 0; i < c1.Count; i++)
            {
                int j = c1.Count - i - 1;
                for (int k = 0; k < c1.Dimension; k++)
                {
                    if (c1.GetOrdinate(i, k) != c2.GetOrdinate(j, k))
                    {
                        if (!(double.IsNaN(c1.GetOrdinate(i, k)) && double.IsNaN(c2.GetOrdinate(j, k))))
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
コード例 #2
0
        /// <summary>
        /// Applies this transformation to the i'th coordinate
        /// in the given CoordinateSequence.
        /// </summary>
        /// <param name="seq"> a <code>CoordinateSequence</code></param>
        /// <param name="i"> the index of the coordinate to transform</param>
        public void Transform(CoordinateSequence seq, int i)
        {
            double xp = _m00 * seq.GetOrdinate(i, 0) + _m01 * seq.GetOrdinate(i, 1) + _m02;
            double yp = _m10 * seq.GetOrdinate(i, 0) + _m11 * seq.GetOrdinate(i, 1) + _m12;

            seq.SetOrdinate(i, 0, xp);
            seq.SetOrdinate(i, 1, yp);
        }
コード例 #3
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="seq">The coordinate sequence</param>
            public void Filter(CoordinateSequence seq, int i)
            {
                double xp = seq.GetOrdinate(i, 0) + _trans.X;
                double yp = seq.GetOrdinate(i, 1) + _trans.Y;

                seq.SetOrdinate(i, 0, xp);
                seq.SetOrdinate(i, 1, yp);
            }
コード例 #4
0
        /// <summary>
        /// Transforms the coordinate at <paramref name="index"/> of <paramref name="sequence"/> to the tile coordinate system.
        /// The return value is the position relative to the local point at (<paramref name="currentX"/>, <paramref name="currentY"/>).
        /// </summary>
        /// <param name="sequence">The input sequence</param>
        /// <param name="index">The index of the coordinate to transform</param>
        /// <param name="currentX">The current horizontal component of the cursor location. This value is updated.</param>
        /// <param name="currentY">The current vertical component of the cursor location. This value is updated.</param>
        /// <returns>The position relative to the local point at (<paramref name="currentX"/>, <paramref name="currentY"/>).</returns>
        public (int x, int y) Transform(CoordinateSequence sequence, int index, ref int currentX, ref int currentY)
        {
            int localX = (int)((sequence.GetOrdinate(index, Ordinate.X) - Left) / LongitudeStep);
            int localY = (int)((Top - sequence.GetOrdinate(index, Ordinate.Y)) / LatitudeStep);
            int dx     = localX - currentX;
            int dy     = localY - currentY;

            currentX = localX;
            currentY = localY;

            return(dx, dy);
        }
コード例 #5
0
            public void Filter(CoordinateSequence seq, int i)
            {
                var result = _transform.Transform(
                    new[]
                {
                    seq.GetOrdinate(i, Ordinate.X),
                    seq.GetOrdinate(i, Ordinate.Y)
                });

                seq.SetOrdinate(i, Ordinate.X, result[0]);
                seq.SetOrdinate(i, Ordinate.Y, result[1]);
            }
コード例 #6
0
                private static void FixSpike(CoordinateSequence seq, int fixIndex, int fixWithIndex)
                {
                    seq.SetOrdinate(fixIndex, Ordinate.X, seq.GetOrdinate(fixWithIndex, Ordinate.X));
                    seq.SetOrdinate(fixIndex, Ordinate.Y, seq.GetOrdinate(fixWithIndex, Ordinate.Y));

                    if ((seq.Ordinates & Ordinates.Z) == Ordinates.Z)
                    {
                        seq.SetOrdinate(fixIndex, Ordinate.Z, seq.GetOrdinate(fixWithIndex, Ordinate.Z));
                    }
                    if ((seq.Ordinates & Ordinates.M) == Ordinates.M)
                    {
                        seq.SetOrdinate(fixIndex, Ordinate.M, seq.GetOrdinate(fixWithIndex, Ordinate.M));
                    }
                }
コード例 #7
0
        // Use map to restore M values on the coordinate array
        private CoordinateSequence restoreDim4(CoordinateSequence cs, Dictionary <Coordinate, Double> map)
        {
            CoordinateSequence seq = new PackedCoordinateSequenceFactory(PackedCoordinateSequenceFactory.PackedType.Double).Create(cs.Count, 4);

            for (int i = 0; i < cs.Count; i++)
            {
                seq.SetOrdinate(i, 0, cs.GetOrdinate(i, 0));
                seq.SetOrdinate(i, 1, cs.GetOrdinate(i, 1));
                seq.SetOrdinate(i, 2, cs.GetOrdinate(i, 2));
                Double d = map[cs.GetCoordinate(i)];
                seq.SetOrdinate(i, 3, d == null ? Double.NaN : d);
            }
            return(seq);
        }
コード例 #8
0
        /// <summary>
        /// Function to return a coordinate sequence that is ensured to be closed.
        /// </summary>
        /// <param name="sequence">The base sequence</param>
        /// <param name="factory">The factory to use in case we need to create a new sequence</param>
        /// <returns>A closed coordinate sequence</returns>
        private static CoordinateSequence EnsureClosedSequence(CoordinateSequence sequence,
                                                               CoordinateSequenceFactory factory)
        {
            //This sequence won't serve a valid linear ring
            if (sequence.Count < 3)
            {
                return(null);
            }

            //The sequence is closed
            var start     = sequence.GetCoordinate(0);
            int lastIndex = sequence.Count - 1;
            var end       = sequence.GetCoordinate(lastIndex);

            if (start.Equals2D(end))
            {
                return(sequence);
            }

            // The sequence is not closed
            // 1. Test for a little offset, in that case simply correct x- and y- ordinate values
            const double eps = 1E-7;

            if (start.Distance(end) < eps)
            {
                sequence.SetX(lastIndex, start.X);
                sequence.SetY(lastIndex, start.Y);
                return(sequence);
            }

            // 2. Close the sequence by adding a new point, this is heavier
            var newSequence = factory.Create(sequence.Count + 1, sequence.Dimension, sequence.Measures);
            int maxDim      = sequence.Dimension;

            for (int i = 0; i < sequence.Count; i++)
            {
                for (int dim = 0; dim < maxDim; dim++)
                {
                    newSequence.SetOrdinate(i, dim, sequence.GetOrdinate(i, dim));
                }
            }

            for (int dim = 0; dim < maxDim; dim++)
            {
                newSequence.SetOrdinate(sequence.Count, dim, sequence.GetOrdinate(0, dim));
            }

            return(newSequence);
        }
コード例 #9
0
        private static void CheckCoordinateAt(CoordinateSequence seq1, int pos1,
                                              CoordinateSequence seq2, int pos2, int dim)
        {
            Assert.AreEqual(seq1.GetOrdinate(pos1, Ordinate.X), seq2.GetOrdinate(pos2, Ordinate.X),
                            "unexpected x-ordinate at pos " + pos2);
            Assert.AreEqual(seq1.GetOrdinate(pos1, Ordinate.Y), seq2.GetOrdinate(pos2, Ordinate.Y),
                            "unexpected y-ordinate at pos " + pos2);

            // check additional ordinates
            for (int j = 2; j < dim; j++)
            {
                Assert.AreEqual(seq1.GetOrdinate(pos1, j), seq2.GetOrdinate(pos2, j),
                                "unexpected " + j + "-ordinate at pos " + pos2);
            }
        }
コード例 #10
0
        protected bool IsAllCoordsEqual(CoordinateSequence seq, Coordinate coord)
        {
            for (int i = 0; i < seq.Count; i++)
            {
                if (!coord.Equals(seq.GetCoordinate(i)))
                {
                    return(false);
                }

                if (coord.X != seq.GetOrdinate(i, 0))
                {
                    return(false);
                }
                if (coord.Y != seq.GetOrdinate(i, 1))
                {
                    return(false);
                }
                if (seq.HasZ)
                {
                    if (coord.Z != seq.GetZ(i))
                    {
                        return(false);
                    }
                }
                if (seq.HasM)
                {
                    if (coord.M != seq.GetM(i))
                    {
                        return(false);
                    }
                }
                if (seq.Dimension > 2)
                {
                    if (coord[2] != seq.GetOrdinate(i, 2))
                    {
                        return(false);
                    }
                }
                if (seq.Dimension > 3)
                {
                    if (coord[3] != seq.GetOrdinate(i, 3))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
コード例 #11
0
            public void Filter(CoordinateSequence seq)
            {
                if (!seq.HasZ)
                {
                    _hasZ = false;
                    return;
                }

                for (int i = 0; i < seq.Count; i++)
                {
                    double z = seq.GetOrdinate(i, Ordinate.Z);
                    _em.Add(seq.GetOrdinate(i, Ordinate.X),
                            seq.GetOrdinate(i, Ordinate.Y),
                            z);
                }
            }
コード例 #12
0
        /**
         * Computes a point which is the average of all coordinates
         * in a sequence.
         * If the sequence lies in a single plane,
         * the computed point also lies in the plane.
         *
         * @param seq a coordinate sequence
         * @return a Coordinate with averaged ordinates
         */
        private static Coordinate AveragePoint(CoordinateSequence seq)
        {
            var a = new CoordinateZ(0, 0, 0);
            int n = seq.Count;

            for (int i = 0; i < n; i++)
            {
                a.X += seq.GetOrdinate(i, 0);
                a.Y += seq.GetOrdinate(i, 1);
                a.Z += seq.GetOrdinate(i, 2);
            }
            a.X /= n;
            a.Y /= n;
            a.Z /= n;
            return(a);
        }
コード例 #13
0
        protected static CoordinateSequence AddCoordinateToSequence(CoordinateSequence sequence,
                                                                    CoordinateSequenceFactory factory,
                                                                    double x, double y, double?z, double?m)
        {
            // Create a new sequence
            var newSequence = factory.Create(sequence.Count + 1, sequence.Dimension, sequence.Measures);

            // Copy old values
            int maxDim = sequence.Dimension;

            for (int i = 0; i < sequence.Count; i++)
            {
                for (int dim = 0; dim < maxDim; dim++)
                {
                    newSequence.SetOrdinate(i, dim, sequence.GetOrdinate(i, dim));
                }
            }

            // new coordinate
            newSequence.SetX(sequence.Count, x);
            newSequence.SetY(sequence.Count, y);
            if (z.HasValue)
            {
                newSequence.SetZ(sequence.Count, z.Value);
            }
            if (m.HasValue)
            {
                newSequence.SetM(sequence.Count, m.Value);
            }

            return(newSequence);
        }
        /// <summary>
        /// Transforms the coordinate at <paramref name="index"/> of <paramref name="sequence"/> to the tile coordinate system.
        /// The return value is the position relative to the local point at (<paramref name="currentX"/>, <paramref name="currentY"/>).
        /// </summary>
        /// <param name="sequence">The input sequence</param>
        /// <param name="index">The index of the coordinate to transform</param>
        /// <param name="currentX">The current horizontal component of the cursor location. This value is updated.</param>
        /// <param name="currentY">The current vertical component of the cursor location. This value is updated.</param>
        /// <returns>The position relative to the local point at (<paramref name="currentX"/>, <paramref name="currentY"/>).</returns>
        public (int x, int y) Transform(CoordinateSequence sequence, int index, ref int currentX, ref int currentY)
        {
            var lon = sequence.GetOrdinate(index, Ordinate.X);
            var lat = sequence.GetOrdinate(index, Ordinate.Y);

            var meters = WebMercatorHandler.LatLonToMeters(lat, lon);
            var pixels = WebMercatorHandler.MetersToPixels(meters, _tile.Zoom, (int)_extent);

            int localX = (int)(pixels.x - _left);
            int localY = (int)(_top - pixels.y);
            int dx     = localX - currentX;
            int dy     = localY - currentY;

            currentX = localX;
            currentY = localY;

            return(dx, dy);
        }
コード例 #15
0
 public override double GetOrdinate(int index, int ordinateIndex)
 {
     // Z ord is always 0
     if (ordinateIndex > 1)
     {
         return(0);
     }
     return(_seq.GetOrdinate(index, _indexMap[ordinateIndex]));
 }
コード例 #16
0
            public void Filter(CoordinateSequence seq)
            {
                if (!seq.HasZ)
                {
                    // if no Z then short-circuit evaluation
                    Done = true;
                    return;
                }

                for (int i = 0; i < seq.Count; i++)
                {
                    // if Z not populated then assign using model
                    if (double.IsNaN(seq.GetZ(i)))
                    {
                        double z = _em.GetZ(seq.GetOrdinate(i, Ordinate.X), seq.GetOrdinate(i, Ordinate.Y));
                        seq.SetOrdinate(i, Ordinate.Z, z);
                    }
                }
            }
コード例 #17
0
        /// <summary>
        /// Evaluates the <see cref="Interval"/> of the <paramref name="ordinate"/>-values in
        /// <paramref name="sequence"/> and writes it using the provided <paramref name="writer"/>
        /// </summary>
        /// <param name="sequence">The sequence</param>
        /// <param name="ordinate">The ordinate</param>
        /// <param name="writer">The writer</param>
        protected void WriteInterval(CoordinateSequence sequence, Ordinate ordinate, BinaryWriter writer)
        {
            Interval interval;

            if (!sequence.TryGetOrdinateIndex(ordinate, out int ordinateIndex))
            {
                interval = ordinate == Ordinate.M
                    ? Interval.Create(ShapeFileConstants.NoDataValue)
                    : Interval.Create(double.NaN);
            }
            else if (ordinate == Ordinate.M)
            {
                double val = sequence.GetOrdinate(0, ordinateIndex);
                if (double.IsNaN(val))
                {
                    val = ShapeFileConstants.NoDataValue;
                }

                interval = Interval.Create(val);
                for (int i = 1, cnt = sequence.Count; i < cnt; i++)
                {
                    val = sequence.GetOrdinate(i, ordinateIndex);
                    if (double.IsNaN(val))
                    {
                        val = ShapeFileConstants.NoDataValue;
                    }

                    interval = interval.ExpandedByValue(val);
                }
            }
            else
            {
                double val = sequence.GetOrdinate(0, ordinateIndex);
                interval = Interval.Create(val);
                for (int i = 1, cnt = sequence.Count; i < cnt; i++)
                {
                    interval = interval.ExpandedByValue(sequence.GetOrdinate(i, ordinateIndex));
                }
            }

            writer.Write(interval.Min);
            writer.Write(interval.Max);
        }
コード例 #18
0
 private void gatherDim4(CoordinateSequence cs, Dictionary <Coordinate, Double> map)
 {
     if (cs.Dimension == 4)
     {
         for (int i = 0; i < cs.Count; i++)
         {
             map.TryAdd(cs.GetCoordinate(i), cs.GetOrdinate(i, 3));
         }
     }
 }
コード例 #19
0
        /// <summary>
        /// Write a <see cref="CoordinateSequence"/>.
        /// </summary>
        /// <param name="sequence">The coordinate sequence to write</param>
        /// <param name="emitSize">A flag indicating if the size of <paramref name="sequence"/> should be written, too.</param>
        /// <param name="writer">The writer.</param>
        protected void Write(CoordinateSequence sequence, bool emitSize, BinaryWriter writer)
        {
            if (emitSize)
            {
                writer.Write(sequence.Count);
            }

            // zm-values if not provided by sequence
            double ordinateZ = Coordinate.NullOrdinate;
            double ordinateM = Coordinate.NullOrdinate;

            // test if zm-values are provided by sequence
            bool getZ = sequence.HasZ;
            bool getM = sequence.HasM;

            // test if zm-values should be emitted
            bool writeZ = (HandleOrdinates & Ordinates.Z) == Ordinates.Z;
            bool writeM = (HandleOrdinates & Ordinates.M) == Ordinates.M;

            for (int index = 0; index < sequence.Count; index++)
            {
                writer.Write(sequence.GetOrdinate(index, 0));
                writer.Write(sequence.GetOrdinate(index, 1));
                if (writeZ)
                {
                    if (getZ)
                    {
                        ordinateZ = sequence.GetZ(index);
                    }
                    writer.Write(ordinateZ);
                }
                if (writeM)
                {
                    if (getM)
                    {
                        ordinateM = sequence.GetM(index);
                    }
                    writer.Write(ordinateM);
                }
            }
        }
コード例 #20
0
        /// <summary>
        /// Checks two <see cref="CoordinateSequence"/>s for equality.  The following items are checked:
        /// <list type="bullet">
        /// <item><description>size</description></item>
        /// <item><description>dimension up to <paramref name="dimension"/></description></item>
        /// <item><description>ordinate values with <paramref name="tolerance"/></description></item>
        /// </list>
        /// </summary>
        /// <param name="seq1">a sequence</param>
        /// <param name="seq2">another sequence</param>
        /// <returns><see langword="true"/> if both sequences are equal.</returns>
        public static bool CheckEqual(CoordinateSequence seq1, CoordinateSequence seq2, int dimension, double tolerance)
        {
            if (ReferenceEquals(seq1, seq2))
            {
                return(true);
            }

            if (seq1 is null || seq2 is null)
            {
                return(false);
            }

            if (seq1.Count != seq2.Count)
            {
                return(false);
            }

            if (seq1.Dimension < dimension)
            {
                throw new ArgumentException("dimension too high for seq1", nameof(seq1));
            }

            if (seq2.Dimension < dimension)
            {
                throw new ArgumentException("dimension too high for seq2", nameof(seq2));
            }

            for (int i = 0, cnt = seq1.Count; i < cnt; i++)
            {
                for (int j = 0; j < dimension; j++)
                {
                    double val1 = seq1.GetOrdinate(i, j);
                    double val2 = seq2.GetOrdinate(i, j);
                    if (double.IsNaN(val1))
                    {
                        if (!double.IsNaN(val2))
                        {
                            return(false);
                        }
                    }
                    else if (Math.Abs(val1 - val2) > tolerance)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
コード例 #21
0
        // If X or Y is null, return an empty Point
        private Point makePointValid(Point point)
        {
            CoordinateSequence        sequence  = point.CoordinateSequence;
            GeometryFactory           factory   = point.Factory;
            CoordinateSequenceFactory csFactory = factory.CoordinateSequenceFactory;

            if (sequence.Count == 0)
            {
                return(point);
            }
            else if (Double.IsNaN(sequence.GetOrdinate(0, 0)) || Double.IsNaN(sequence.GetOrdinate(0, 1)))
            {
                return(factory.CreatePoint(csFactory.Create(0, sequence.Dimension)));
            }
            else if (sequence.Count == 1)
            {
                return(point);
            }
            else
            {
                throw new Exception();
                //throw new RuntimeException("JTS cannot Create a point from a CoordinateSequence containing several points");
            }
        }
コード例 #22
0
ファイル: MLineString.cs プロジェクト: nemesv/ASTRA.EMSG
        /**
         * Returns the measure length of the segment. This method assumes that the
         * length of the LineString is defined by the absolute value of (last
         * coordinate - first coordinate) in the CoordinateSequence. If either
         * measure is not defined or the CoordinateSequence contains no coordinates,
         * then Double.NaN is returned. If there is only 1 element in the
         * CoordinateSequence, then 0 is returned.
         *
         * @return The measure length of the LineString
         */
        public double GetMLength()
        {
            if (CoordinateSequence.Count == 0)
            {
                return(Double.NaN);
            }
            if (CoordinateSequence.Count == 1)
            {
                return(0.0D);
            }

            int    lastIndex = CoordinateSequence.Count - 1;
            double begin     = CoordinateSequence.GetOrdinate(0, Ordinate.M);
            double end       = CoordinateSequence.GetOrdinate(lastIndex, Ordinate.M);

            return((Double.IsNaN(begin) || Double.IsNaN(end)) ? Double.NaN : Math.Abs(end - begin));
        }
コード例 #23
0
        private static CoordinateSequence InsertTopologyExceptionPoint(Coordinate coord, CoordinateSequence seq, CoordinateSequenceFactory factory)
        {
            var res = factory.Create(2 * seq.Count, seq.Ordinates);

            if (Replace(seq.GetCoordinate(0), coord))
            {
                res.SetOrdinate(0, Ordinate.X, coord.X);
                res.SetOrdinate(0, Ordinate.Y, coord.Y);
                res.SetOrdinate(0, Ordinate.Z, coord.Z);
            }
            else
            {
                res.SetOrdinate(0, Ordinate.X, seq.GetOrdinate(0, Ordinate.X));
                res.SetOrdinate(0, Ordinate.Y, seq.GetOrdinate(0, Ordinate.Y));
                res.SetOrdinate(0, Ordinate.Z, seq.GetOrdinate(0, Ordinate.Z));
            }

            var last = res.GetCoordinate(0);
            int off  = 0;

            for (int i = 1; i < seq.Count; i++)
            {
                var  curr = seq.GetCoordinate(i);
                bool add  = true;
                if (Replace(curr, coord))
                {
                    res.SetOrdinate(i + off, Ordinate.X, coord.X);
                    res.SetOrdinate(i + off, Ordinate.Y, coord.Y);
                    res.SetOrdinate(i + off, Ordinate.Z, coord.Z);
                    add = false;
                }
                else if (last.Distance(coord) + coord.Distance(curr) <= 1.000000000000000000001 * last.Distance(curr))
                {
                    res.SetOrdinate(i + off, Ordinate.X, coord.X);
                    res.SetOrdinate(i + off, Ordinate.Y, coord.Y);
                    res.SetOrdinate(i + off, Ordinate.Z, coord.Z);
                    off += 1;
                }

                if (add)
                {
                    res.SetOrdinate(i + off, Ordinate.X, seq.GetOrdinate(i, Ordinate.X));
                    res.SetOrdinate(i + off, Ordinate.Y, seq.GetOrdinate(i, Ordinate.Y));
                    res.SetOrdinate(i + off, Ordinate.Z, seq.GetOrdinate(i, Ordinate.Z));
                }
                last = curr;
            }

            var tmp = factory.Create(seq.Count + off, seq.Ordinates);

            CoordinateSequences.Copy(res, 0, tmp, 0, tmp.Count);
            return(tmp);
        }
コード例 #24
0
        private static CoordinateSequence SetDimension(CoordinateSequenceFactory fact, CoordinateSequence seq,
                                                       int dimension)
        {
            if (seq.Dimension == dimension && seq.Measures == 0)
            {
                return(seq);
            }

            var res = fact.Create(seq.Count, dimension, 0);

            dimension = Math.Min(dimension, seq.Dimension);
            for (int i = 0; i < seq.Count; i++)
            {
                for (int j = 0; j < dimension; j++)
                {
                    res.SetOrdinate(i, j, seq.GetOrdinate(i, j));
                }
            }
            return(res);
        }
コード例 #25
0
        private static void DoTest(CoordinateSequence forward, CoordinateSequence reversed)
        {
            const double eps = 1e-12;

            Assert.AreEqual(forward.Count, reversed.Count, "Coordinate sequences don't have same size");
            Assert.AreEqual(forward.Ordinates, reversed.Ordinates, "Coordinate sequences don't serve same ordinate values");

            var ordinates = ToOrdinateArray(forward.Ordinates);
            int j         = forward.Count;

            for (int i = 0; i < forward.Count; i++)
            {
                j--;
                foreach (var ordinate in ordinates)
                {
                    Assert.AreEqual(forward.GetOrdinate(i, ordinate), reversed.GetOrdinate(j, ordinate), eps, string.Format("{0} values are not within tolerance", ordinate));
                }
                var cf = forward.GetCoordinate(i);
                var cr = reversed.GetCoordinate(j);

                Assert.IsFalse(ReferenceEquals(cf, cr), "Coordinate sequences deliver same coordinate instances");
                Assert.IsTrue(cf.Equals(cr), "Coordinate sequences do not provide equal coordinates");
            }
        }
コード例 #26
0
        /**
         * Returns a coordinateSequence free of Coordinates with X or Y NaN value,
         * and if desired, free of duplicated coordinates. makeSequenceValid keeps
         * the original dimension of input sequence.
         *
         * @param sequence input sequence of coordinates
         * @param preserveDuplicateCoord if duplicate coordinates must be preserved
         * @param close if the sequence must be closed
         * @return a new CoordinateSequence with valid XY values
         */
        private static CoordinateSequence makeSequenceValid(CoordinateSequence sequence,
                                                            bool preserveDuplicateCoord, bool close)
        {
            int dim = sequence.Dimension;

            // we Add 1 to the sequence size for the case where we have to close the linear ring
            double[] array    = new double[(sequence.Count + 1) * sequence.Dimension];
            bool     modified = false;
            int      count    = 0;

            // Iterate through coordinates, skip points with x=NaN, y=NaN or duplicate
            for (int i = 0; i < sequence.Count; i++)
            {
                if (Double.IsNaN(sequence.GetOrdinate(i, 0)) || Double.IsNaN(sequence.GetOrdinate(i, 1)))
                {
                    modified = true;
                    continue;
                }
                if (!preserveDuplicateCoord && count > 0 && sequence.GetCoordinate(i).Equals(sequence.GetCoordinate(i - 1)))
                {
                    modified = true;
                    continue;
                }
                for (int j = 0; j < dim; j++)
                {
                    array[count * dim + j] = sequence.GetOrdinate(i, j);
                    if (j == dim - 1)
                    {
                        count++;
                    }
                }
            }
            // Close the sequence if it is not closed and there is already 3 distinct coordinates
            if (close && count > 2 && (array[0] != array[(count - 1) * dim] || array[1] != array[(count - 1) * dim + 1]))
            {
                System.Array.Copy(array, 0, array, count * dim, dim);
                modified = true;
                count++;
            }
            // Close z, m dimension if needed
            if (close && count > 3 && dim > 2)
            {
                for (int d = 2; d < dim; d++)
                {
                    if (array[(count - 1) * dim + d] != array[d])
                    {
                        modified = true;
                    }
                    array[(count - 1) * dim + d] = array[d];
                }
            }
            if (modified)
            {
                double[] shrinkedArray = new double[count * dim];
                System.Array.Copy(array, 0, shrinkedArray, 0, count * dim);
                return(PackedCoordinateSequenceFactory.DoubleFactory.Create(shrinkedArray, dim));
            }
            else
            {
                return(sequence);
            }
        }
コード例 #27
0
        /// <summary>
        /// Tests for equality using all supported accessors,
        /// to provides test coverage for them.
        /// </summary>
        /// <param name="seq"></param>
        /// <param name="coords"></param>
        /// <returns></returns>
        protected bool IsEqual(CoordinateSequence seq, Coordinate[] coords)
        {
            if (seq.Count != coords.Length)
            {
                return(false);
            }

            // carefully get coordinate of the same type as the sequence
            var p = seq.CreateCoordinate();

            for (int i = 0; i < seq.Count; i++)
            {
                if (!coords[i].Equals(seq.GetCoordinate(i)))
                {
                    return(false);
                }

                // Ordinate named getters
                if (!coords[i].X.Equals(seq.GetX(i)))
                {
                    return(false);
                }
                if (!coords[i].Y.Equals(seq.GetY(i)))
                {
                    return(false);
                }
                if (seq.HasZ)
                {
                    if (!coords[i].Z.Equals(seq.GetZ(i)))
                    {
                        return(false);
                    }
                }
                if (seq.HasM)
                {
                    if (!coords[i].M.Equals(seq.GetM(i)))
                    {
                        return(false);
                    }
                }

                // Ordinate indexed getters
                if (!coords[i].X.Equals(seq.GetOrdinate(i, 0)))
                {
                    return(false);
                }
                if (!coords[i].Y.Equals(seq.GetOrdinate(i, 1)))
                {
                    return(false);
                }
                if (seq.Dimension > 2)
                {
                    if (!coords[i][2].Equals(seq.GetOrdinate(i, 2)))
                    {
                        return(false);
                    }
                }
                if (seq.Dimension > 3)
                {
                    if (!coords[i][3].Equals(seq.GetOrdinate(i, 3)))
                    {
                        return(false);
                    }
                }

                // Coordinate getter
                seq.GetCoordinate(i, p);
                if (!coords[i].X.Equals(p.X))
                {
                    return(false);
                }
                if (!coords[i].Y.Equals(p.Y))
                {
                    return(false);
                }
                if (seq.HasZ)
                {
                    if (!coords[i].Z.Equals(p.Z))
                    {
                        return(false);
                    }
                }
                if (seq.HasM)
                {
                    if (!coords[i].M.Equals(p.M))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
コード例 #28
0
 /// <summary>
 /// Rounds the Coordinates in the sequence to match the PrecisionModel
 /// </summary>
 public void Filter(CoordinateSequence seq, int i)
 {
     seq.SetOrdinate(i, 0, _precModel.MakePrecise(seq.GetOrdinate(i, 0)));
     seq.SetOrdinate(i, 1, _precModel.MakePrecise(seq.GetOrdinate(i, 1)));
 }
コード例 #29
0
        /// <summary>
        /// Tests if a ring defined by a <see cref="CoordinateSequence"/> is
        /// oriented counter-clockwise.
        /// <list type="bullet">
        /// <item><description>The list of points is assumed to have the first and last points equal.</description></item>
        /// <item><description>This handles coordinate lists which contain repeated points.</description></item>
        /// <item><description>This handles rings which contain collapsed segments (in particular, along the top of the ring).</description></item>
        /// </list>
        /// This algorithm is guaranteed to work with valid rings.
        /// It also works with "mildly invalid" rings
        /// which contain collapsed(coincident) flat segments along the top of the ring.
        /// If the ring is "more" invalid (e.g.self-crosses or touches),
        /// the computed result may not be correct.
        /// </summary>
        /// <param name="ring">A <c>CoordinateSequence</c>s forming a ring (with first and last point identical).</param>
        /// <returns><c>true</c> if the ring is oriented counter-clockwise.</returns>
        /// <exception cref="ArgumentException">Thrown if there are too few points to determine orientation (&lt; 4)</exception>
        public static bool IsCCW(CoordinateSequence ring)
        {
            // # of points without closing endpoint
            int nPts = ring.Count - 1;

            // sanity check
            if (nPts < 3)
            {
                throw new ArgumentException(
                          "Ring has fewer than 4 points, so orientation cannot be determined", nameof(ring));
            }

            /*
             * Find first highest point after a lower point, if one exists
             * (e.g. a rising segment)
             * If one does not exist, hiIndex will remain 0
             * and the ring must be flat.
             * Note this relies on the convention that
             * rings have the same start and end point.
             */
            var        upHiPt  = ring.GetCoordinate(0);
            double     prevY   = upHiPt.Y;
            Coordinate upLowPt = null;
            int        iUpHi   = 0;

            for (int i = 1; i <= nPts; i++)
            {
                double py = ring.GetOrdinate(i, Ordinate.Y);

                /*
                 * If segment is upwards and endpoint is higher, record it
                 */
                if (py > prevY && py >= upHiPt.Y)
                {
                    upHiPt  = ring.GetCoordinate(i);
                    iUpHi   = i;
                    upLowPt = ring.GetCoordinate(i - 1);
                }
                prevY = py;
            }

            /*
             * Check if ring is flat and return default value if so
             */
            if (iUpHi == 0)
            {
                return(false);
            }

            /*
             * Find the next lower point after the high point
             * (e.g. a falling segment).
             * This must exist since ring is not flat.
             */
            int iDownLow = iUpHi;

            do
            {
                iDownLow = (iDownLow + 1) % nPts;
            } while (iDownLow != iUpHi && ring.GetOrdinate(iDownLow, Ordinate.Y) == upHiPt.Y);

            var downLowPt = ring.GetCoordinate(iDownLow);
            int iDownHi   = iDownLow > 0 ? iDownLow - 1 : nPts - 1;
            var downHiPt  = ring.GetCoordinate(iDownHi);

            /*
             * Two cases can occur:
             * 1) the hiPt and the downPrevPt are the same.
             *    This is the general position case of a "pointed cap".
             *    The ring orientation is determined by the orientation of the cap
             * 2) The hiPt and the downPrevPt are different.
             *    In this case the top of the cap is flat.
             *    The ring orientation is given by the direction of the flat segment
             */
            if (upHiPt.Equals2D(downHiPt))
            {
                /*
                 * Check for the case where the cap has configuration A-B-A.
                 * This can happen if the ring does not contain 3 distinct points
                 * (including the case where the input array has fewer than 4 elements), or
                 * it contains coincident line segments.
                 */
                if (upLowPt.Equals2D(upHiPt) || downLowPt.Equals2D(upHiPt) || upLowPt.Equals2D(downLowPt))
                {
                    return(false);
                }

                /*
                 * It can happen that the top segments are coincident.
                 * This is an invalid ring, which cannot be computed correctly.
                 * In this case the orientation is 0, and the result is false.
                 */
                var index = Index(upLowPt, upHiPt, downLowPt);
                return(index == OrientationIndex.CounterClockwise);
            }
            else
            {
                /*
                 * Flat cap - direction of flat top determines orientation
                 */
                double delX = downHiPt.X - upHiPt.X;
                return(delX < 0);
            }
        }