Example #1
0
        /// <summary>
        /// Advances the vertex index of coordsToAdvance starting at currentIndex until
        /// the point at the index matches coordinateToMatch. All intermediate points are
        /// added to changedCoords.
        /// </summary>
        /// <param name="coordsToAdvance">The list of coordinates (sorted) to go through
        /// until a coordinate matches <paramref name="coordinateToMatch"/>.</param>
        /// <param name="index">The index to start at which shall be incremented unit the coordinates match.</param>
        /// <param name="coordinateToMatch">The target coordinate.</param>
        /// <param name="comparer">The comparer.</param>
        /// <param name="changedCoords">The list of coordinates that do not match.</param>
        /// <param name="addChangesToResult">Whether the changed points should be added to changedCoords</param>
        /// <param name="reportDuplicateVertices">Whether duplicate vertices in the coordsToAdvance should be reported or not.</param>
        /// <returns>Whether a match was found or not.</returns>
        private bool AdvanceIndexUntilMatch(
            [NotNull] WKSPointZ[] coordsToAdvance,
            ref int index,
            WKSPointZ coordinateToMatch,
            [NotNull] IComparer <WKSPointZ> comparer,
            [NotNull] ICollection <WKSPointZ> changedCoords,
            bool addChangesToResult,
            bool reportDuplicateVertices)
        {
            WKSPointZ currentCoord = coordsToAdvance[index];

            while (comparer.Compare(coordinateToMatch, currentCoord) >= 0 &&
                   index < coordsToAdvance.Length)
            {
                // check if within the tolerance - performance could be improved if comparer could directly handle
                // the tolerance.
                bool useTolerance = Math.Abs(_xyTolerance) > double.Epsilon ||
                                    (!double.IsNaN(_zTolerance) &&
                                     Math.Abs(_zTolerance) > double.Epsilon);

                if (useTolerance &&
                    GeometryUtils.IsSamePoint(currentCoord, coordinateToMatch,
                                              _xyTolerance, _zTolerance))
                {
                    return(true);
                }

                if (addChangesToResult)
                {
                    // except if it's a duplicate that should not be reported
                    bool sameAsPrevious = WKSPointZUtils.ArePointsEqual(
                        coordsToAdvance, index, index - 1,
                        _xyTolerance, _zTolerance);

                    if (!sameAsPrevious || reportDuplicateVertices)
                    {
                        changedCoords.Add(currentCoord);
                    }
                }

                ++index;

                if (index < coordsToAdvance.Length)
                {
                    currentCoord = coordsToAdvance[index];
                }
            }

            return(false);
        }
Example #2
0
        /// <summary>
        /// Adds the remaining points starting from baseIndexStart for baseCoords and from
        /// compareIndexStart for compareCoords.
        /// </summary>
        /// <param name="baseCoords"></param>
        /// <param name="compareCoords"></param>
        /// <param name="baseIndexStart"></param>
        /// <param name="compareIndexStart"></param>
        /// <param name="result"></param>
        /// <param name="reportDuplicateVertices"></param>
        /// <param name="baseInsertsOnly"></param>
        private void AddRemainingPoints(
            WKSPointZ[] baseCoords,
            WKSPointZ[] compareCoords,
            int baseIndexStart,
            int compareIndexStart,
            List <WKSPointZ> result,
            bool reportDuplicateVertices,
            bool baseInsertsOnly)
        {
            // add all remaining points from baseCoords
            for (int i = baseIndexStart; i < baseCoords.Length; i++)
            {
                bool sameAsPrevious = WKSPointZUtils.ArePointsEqual(
                    baseCoords, i, i - 1, _xyTolerance,
                    _zTolerance);

                if (sameAsPrevious && !reportDuplicateVertices)
                {
                    continue;
                }

                result.Add(baseCoords[i]);
            }

            if (!baseInsertsOnly)
            {
                // add all remaining points from baseCoords
                for (int i = compareIndexStart; i < compareCoords.Length; i++)
                {
                    bool sameAsPrevious = WKSPointZUtils.ArePointsEqual(compareCoords, i, i - 1,
                                                                        _xyTolerance,
                                                                        _zTolerance);

                    if (sameAsPrevious && !reportDuplicateVertices)
                    {
                        continue;
                    }

                    result.Add(compareCoords[i]);
                }
            }
        }
Example #3
0
        private IList <WKSPointZ> GetChangedVertices(
            WKSPointZ[] baseCoords, WKSPointZ[] compareCoords,
            bool reportDuplicateVertices, bool baseInsertsOnly)
        {
            Assert.ArgumentNotNull(baseCoords, nameof(baseCoords));
            Assert.ArgumentNotNull(compareCoords, nameof(compareCoords));

            var comparer = new WKSPointZComparer(_xyTolerance, _zTolerance, 0, 0, 0);

            Array.Sort(baseCoords, comparer);
            Array.Sort(compareCoords, comparer);

            var result = new List <WKSPointZ>();

            var i1 = 0;
            var i2 = 0;

            while (i1 < baseCoords.Length && i2 < compareCoords.Length)
            {
                WKSPointZ a = baseCoords[i1];
                WKSPointZ b = compareCoords[i2];

                bool inSync = GeometryUtils.IsSamePoint(a, b, _xyTolerance, _zTolerance);

                if (!inSync)
                {
                    // a is greater than b, advance b until in sync with a
                    bool matchAdvanceCompareCoords = AdvanceIndexUntilMatch(
                        compareCoords, ref i2, a, comparer, result, !baseInsertsOnly,
                        reportDuplicateVertices);

                    // b is greater than a, advance a until in sync with b
                    bool matchAdvanceBaseCoords = AdvanceIndexUntilMatch(
                        baseCoords, ref i1, b, comparer, result, true, reportDuplicateVertices);

                    if (matchAdvanceCompareCoords || matchAdvanceBaseCoords)
                    {
                        inSync = true;
                    }
                }

                // Advance to next set of coordinates only if in sync to make sure no difference points are missed
                if (inSync)
                {
                    ++i1;
                    ++i2;
                }

                // Skip identical points in sequence otherwise From/To points in rotated ring get reported as changes
                // NOTE: SameCoords tolerates index out of bounds!
                while (WKSPointZUtils.ArePointsEqual(baseCoords, i1, i1 - 1, _xyTolerance,
                                                     _zTolerance))
                {
                    bool compareCoordsHasDuplicateToo =
                        inSync &&
                        WKSPointZUtils.ArePointsEqual(compareCoords, i2, i2 - 1, _xyTolerance,
                                                      _zTolerance);

                    if (compareCoordsHasDuplicateToo)
                    {
                        // in sync and both have a duplicate at the same location -> unchanged, do not report
                        // but increment both indexes
                        ++i2;
                    }
                    else
                    {
                        // not in sync or compare geometry has no duplicate -> changed, report on request
                        if (reportDuplicateVertices)
                        {
                            result.Add(baseCoords[i1]);
                        }
                    }

                    // eventually landing at the next non-identical point:
                    ++i1;
                }

                // process remaining duplicates at current location (or at original location if not in sync)
                while (WKSPointZUtils.ArePointsEqual(compareCoords, i2, i2 - 1, _xyTolerance,
                                                     _zTolerance))
                {
                    if (reportDuplicateVertices && !baseInsertsOnly)
                    {
                        result.Add(compareCoords[i2]);
                    }

                    ++i2;
                }
            }

            AddRemainingPoints(baseCoords, compareCoords, i1, i2, result,
                               reportDuplicateVertices, baseInsertsOnly);

            return(result);
        }