private MeanSegmentLengthProvider GetMeanSegmentLengthProvider(IFeature row)
        {
            MeanSegmentLengthProvider provider;

            if (!_is3D && row.Shape is ICurve)
            {
                provider = new CurveMeanSegmentsLengthProvider((ICurve)row.Shape, _perPart);
            }
            else
            {
                var segmentsFeature = row as IIndexedSegmentsFeature;
                if (segmentsFeature != null && segmentsFeature.AreIndexedSegmentsLoaded)
                {
                    provider = new IndexedMeanLengthProvider(row.Shape,
                                                             segmentsFeature.IndexedSegments,
                                                             _perPart, _is3D);
                }
                else if (row.Shape is IMultiPatch)
                {
                    IIndexedSegments indexedSegments =
                        QaGeometryUtils.CreateIndexedMultiPatch((IMultiPatch)row.Shape);
                    provider = new IndexedMeanLengthProvider(row.Shape, indexedSegments, _perPart,
                                                             _is3D);
                }
                else
                {
                    provider = new SegmentCollectionMeanLengthProvider(
                        (ISegmentCollection)row.Shape,
                        _perPart, _is3D);
                }
            }

            return(provider);
        }
Exemple #2
0
        public PointFeaturePointEnumerator([NotNull] IFeature feature)
            : base(feature)
        {
            var point = (IPoint)feature.Shape;

            _point = QaGeometryUtils.CreatePoint3D(point);
        }
            protected override bool GetNextSliverArea(out double area, out double perimeter)
            {
                _latestPartSegments = null;
                if (!_enumValid)
                {
                    area      = double.NaN;
                    perimeter = double.NaN;
                    return(false);
                }

                SegmentProxy segment = Assert.NotNull(_segmentsEnum.Current);

                int currentPart  = segment.PartIndex;
                int segmentCount = _indexedMultiPatch.GetPartSegmentCount(currentPart);
                var partSegments = new List <SegmentProxy>(segmentCount)
                {
                    segment
                };

                while ((_enumValid = _segmentsEnum.MoveNext()) &&
                       Assert.NotNull(_segmentsEnum.Current).PartIndex == currentPart)
                {
                    partSegments.Add(_segmentsEnum.Current);
                }

                List <Pnt> planePoints = QaGeometryUtils.GetPoints(partSegments);
                Plane      plane       = QaGeometryUtils.CreatePlane((IEnumerable <SegmentProxy>)partSegments);

                QaGeometryUtils.CalculateProjectedArea(plane, planePoints, out area, out perimeter);

                _latestPartSegments = partSegments;

                return(true);
            }
        public ExceptionObjectEvaluator(
            [NotNull] IEnumerable <ExceptionObject> exceptionObjects,
            [NotNull] IDictionary <Guid, QualityCondition> conditionsByUuid,
            [NotNull] IExceptionEvaluationStatistics exceptionEvaluationStatistics,
            [NotNull] IQualityConditionObjectDatasetResolver datasetResolver,
            [CanBeNull] InvolvedObjectsMatchCriteria involvedObjectsMatchCriteria,
            [CanBeNull] IGeometry areaOfInterest)
        {
            Assert.ArgumentNotNull(exceptionObjects, nameof(exceptionObjects));
            Assert.ArgumentNotNull(conditionsByUuid, nameof(conditionsByUuid));
            Assert.ArgumentNotNull(exceptionEvaluationStatistics,
                                   nameof(exceptionEvaluationStatistics));
            Assert.ArgumentNotNull(datasetResolver, nameof(datasetResolver));

            _conditionsByUuid = conditionsByUuid;
            _exceptionEvaluationStatistics = exceptionEvaluationStatistics;
            _datasetResolver = datasetResolver;
            _involvedObjectsMatchCriteria = involvedObjectsMatchCriteria;

            _aoiBox = areaOfInterest == null || areaOfInterest.IsEmpty
                                          ? null
                                          : QaGeometryUtils.CreateBox(areaOfInterest.Envelope);

            foreach (ExceptionObject exceptionObject in exceptionObjects)
            {
                Add(exceptionObject);
            }
        }
        private SliverAreaProvider GetSliverAreaProvider([NotNull] IFeature feature)
        {
            Assert.ArgumentNotNull(feature, nameof(feature));

            if (_useFields)
            {
                return(new FromFieldsSliverAreaProvider(feature, _areaFieldIndex,
                                                        _lengthFieldIndex));
            }

            if (feature.Shape is IPolygon)
            {
                return(new PolygonRingsSliverAreaProvider((IPolygon)feature.Shape));
            }

            if (feature.Shape is IMultiPatch)
            {
                var indexedMultiPatchFeature = feature as IIndexedMultiPatchFeature;

                IIndexedMultiPatch indexedMultiPatch =
                    indexedMultiPatchFeature != null
                                                ? indexedMultiPatchFeature.IndexedMultiPatch
                                                : QaGeometryUtils.CreateIndexedMultiPatch((IMultiPatch)feature.Shape);

                return(new MultiPatchPartsSliverAreaProvider(indexedMultiPatch));
            }

            throw new InvalidOperationException("feature is unhandled");
        }
        private static bool IsDone([NotNull] IGeometry geometry, WKSEnvelope tileEnvelope)
        {
            WKSEnvelope geometryEnvelope = QaGeometryUtils.GetWKSEnvelope(geometry);

            return(geometryEnvelope.XMax < tileEnvelope.XMax &&
                   geometryEnvelope.YMax < tileEnvelope.YMax);
        }
Exemple #7
0
        private IBox GetCurrentRowToleranceBox(int tableIndex)
        {
            if (CurrentTestRow == null)
            {
                return(null);
            }

            if (_cachedRow == null)
            {
                return(QaGeometryUtils.CreateBox(CurrentTestRow.DataReference.Extent));
            }

            IBox currentBox = _cachedRow.Extent;

            double searchTolerance = GetSearchTolerance(_cachedTableIndex, tableIndex);

            IBox toleranceBox = currentBox.Clone();

            toleranceBox.Min.X -= searchTolerance;
            toleranceBox.Min.Y -= searchTolerance;
            toleranceBox.Max.X += searchTolerance;
            toleranceBox.Max.Y += searchTolerance;

            return(toleranceBox);
        }
        private SegmentLengthProvider GetSegmentLengthProvider(IFeature row)
        {
            SegmentLengthProvider provider;

            var segmentsFeature = row as IIndexedSegmentsFeature;

            if (segmentsFeature != null && segmentsFeature.AreIndexedSegmentsLoaded)
            {
                provider = new IndexedSegmentsLengthProvider(segmentsFeature.IndexedSegments,
                                                             _is3D);
            }
            else if (row.Shape is IMultiPatch)
            {
                IIndexedSegments indexedSegments =
                    QaGeometryUtils.CreateIndexedMultiPatch((IMultiPatch)row.Shape);
                provider = new IndexedSegmentsLengthProvider(indexedSegments, _is3D);
            }
            else
            {
                provider = new SegmentCollectionLengthProvider((ISegmentCollection)row.Shape,
                                                               _is3D);
            }

            return(provider);
        }
Exemple #9
0
 public override IEnumerable <Pnt> GetPoints()
 {
     foreach (WKSPointZ wksPoint in _wksPoints)
     {
         yield return(QaGeometryUtils.CreatePoint3D(wksPoint));
     }
 }
            private IGeometry GetGeometry(int partIndex)
            {
                IGeometry geometry;

                if (!_perPart)
                {
                    geometry = GeometryFactory.Clone(_baseGeometry);
                }
                else if (_baseGeometry is ICurve)
                {
                    var geometryCollection = _baseGeometry as IGeometryCollection;
                    if (geometryCollection == null || geometryCollection.GeometryCount == 1)
                    {
                        geometry = GetErrorGeometry((ICurve)_baseGeometry);
                    }
                    else
                    {
                        var curve = (ICurve)geometryCollection.get_Geometry(partIndex);
                        geometry = GetErrorGeometry(curve);
                    }

                    return(geometry);
                }
                else
                {
                    IGeometryCollection geometryCollection;
                    if (_baseGeometry.GeometryType == esriGeometryType.esriGeometryPolygon)
                    {
                        geometryCollection = QaGeometryUtils.CreatePolygon(_baseGeometry);
                    }
                    else if (_baseGeometry.GeometryType == esriGeometryType.esriGeometryPolyline)
                    {
                        geometryCollection = QaGeometryUtils.CreatePolyline(_baseGeometry);
                    }
                    else if (_baseGeometry.GeometryType == esriGeometryType.esriGeometryMultiPatch)
                    {
                        geometryCollection = new MultiPatchClass();
                    }
                    else
                    {
                        throw new InvalidOperationException("unhandled geometry type " +
                                                            _baseGeometry.GeometryType);
                    }

                    int segmentCount = _indexedSegments.GetPartSegmentCount(partIndex);
                    var partSegments = new List <SegmentProxy>(segmentCount);
                    for (int iSegment = 0; iSegment < segmentCount; iSegment++)
                    {
                        partSegments.Add(_indexedSegments.GetSegment(partIndex, iSegment));
                    }

                    SegmentUtils.CreateGeometry(geometryCollection, partSegments);
                    geometry = (IGeometry)geometryCollection;
                }

                return(geometry);
            }
Exemple #11
0
        private static IIndexedMultiPatch GetIndexedMultiPatch([NotNull] IFeature feature)
        {
            var indexedMultiPatchFeature = feature as IIndexedMultiPatchFeature;

            return(indexedMultiPatchFeature != null
                                       ? indexedMultiPatchFeature.IndexedMultiPatch
                                       : QaGeometryUtils.CreateIndexedMultiPatch(
                       (IMultiPatch)feature.Shape));
        }
        public IEnumerable <ExceptionObject> Search([NotNull] IGeometry geometry)
        {
            if (_boxTree == null)
            {
                _boxTree = CreateBoxTree(_exceptionObjects, _xyTolerance);

                _exceptionObjects.Clear();
            }

            if (_boxTree.Count == 0 || geometry.IsEmpty)
            {
                yield break;
            }

            IBox searchBox = QaGeometryUtils.CreateBox(geometry, _xyTolerance);

            IBox issueBox        = null;
            IBox clippedIssueBox = null;

            foreach (BoxTree <ExceptionObject> .TileEntry tileEntry in _boxTree.Search(searchBox)
                     )
            {
                ExceptionObject exceptionObject = tileEntry.Value;

                if (issueBox == null)
                {
                    issueBox = GetBox(geometry);
                }

                if (Matches(exceptionObject, tileEntry.Box, issueBox))
                {
                    yield return(exceptionObject);
                }
                else
                {
                    // Check if clipped envelope matches
                    if (_areaOfInterestBox == null ||
                        _areaOfInterestBox.Contains(issueBox) ||
                        exceptionObject.AreaOfInterestShapeEnvelope == null)
                    {
                        continue;
                    }

                    if (clippedIssueBox == null)
                    {
                        clippedIssueBox = GetBox(GetClippedGeometry(geometry, _areaOfInterestBox));
                    }

                    if (Matches(exceptionObject, exceptionObject.AreaOfInterestShapeEnvelope,
                                clippedIssueBox))
                    {
                        yield return(exceptionObject);
                    }
                }
            }
        }
        private static VerticalFaceProvider GetPlaneProvider([NotNull] IFeature feature)
        {
            var indexedMultiPatchFeature = feature as IIndexedMultiPatchFeature;

            IIndexedMultiPatch indexedMultiPatch =
                indexedMultiPatchFeature?.IndexedMultiPatch ??
                QaGeometryUtils.CreateIndexedMultiPatch((IMultiPatch)feature.Shape);

            return(new PartVerticalFaceProvider(indexedMultiPatch));
        }
        private HeightSegmentPairProvider GetHeightSegmentPairProvider(
            [NotNull] IFeature feature)
        {
            var indexedFeature            = feature as IIndexedMultiPatchFeature;
            IIndexedMultiPatch multiPatch = indexedFeature?.IndexedMultiPatch ??
                                            QaGeometryUtils.CreateIndexedMultiPatch(
                (IMultiPatch)feature.Shape);

            return(new MultipatchHeightSegmentPairProvider(_nearHeight, multiPatch));
        }
Exemple #15
0
        public static bool VerifyHandled([NotNull] IGeometry geometry,
                                         WKSEnvelope tileEnvelope,
                                         WKSEnvelope allEnvelope)
        {
            WKSEnvelope geometryEnvelope = QaGeometryUtils.GetWKSEnvelope(geometry);

            return((tileEnvelope.XMax >= allEnvelope.XMax ||
                    geometryEnvelope.XMax < tileEnvelope.XMax) &&
                   (tileEnvelope.YMax >= allEnvelope.YMax ||
                    geometryEnvelope.YMax < tileEnvelope.YMax));
        }
Exemple #16
0
 public override IEnumerable <Pnt> GetPoints(IBox searchBox)
 {
     foreach (WKSPointZ wksPoint in _wksPoints)
     {
         Pnt point = QaGeometryUtils.CreatePoint3D(wksPoint);
         if (searchBox.Contains((IPnt)point))
         {
             yield return(point);
         }
     }
 }
Exemple #17
0
        protected override int CompleteTileCore(TileInfo args)
        {
            if (args.State == TileState.Initial)
            {
                _tileFeatures.Clear();
                _tileAreasOfInterest.Clear();
                _allBox    = null;
                _knownGaps = null;
                return(NoError);
            }

            try
            {
                if (_allBox == null)
                {
                    Assert.NotNull(args.AllBox, "args.AllBox");
                    _allBox = QaGeometryUtils.CreateBox(Assert.NotNull(args.AllBox, "AllBox"));
                }

                if (_knownGaps == null)
                {
                    _knownGaps = new KnownGaps(_maxArea, _tolerance, _allBox);
                }

                Assert.NotNull(args.CurrentEnvelope, "args.CurrentEnvelope");
                IEnvelope tileEnvelope =
                    GeometryFactory.Clone(Assert.NotNull(args.CurrentEnvelope, "CurrentEnvelope"));
                tileEnvelope.SpatialReference = _spatialReference;

                var errorCount = 0;

                foreach (IEnvelope subtile in GetSubtiles(tileEnvelope))
                {
                    errorCount += CheckSubtile(subtile, _allBox, _tileFeatures, _knownGaps);

                    // this can be the entire (cloned) tileEnvelope:
                    Marshal.ReleaseComObject(subtile);

                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }

                if (args.State == TileState.Final)
                {
                    _knownGaps = null;
                }

                return(errorCount);
            }
            finally
            {
                _tileFeatures.Clear();
            }
        }
Exemple #18
0
        private static IGeometry GetErrorGeometry([NotNull] ISegment segment)
        {
            Assert.ArgumentNotNull(segment, nameof(segment));

            object missing = Type.Missing;

            PolylineClass result = QaGeometryUtils.CreatePolyline(segment);

            ((ISegmentCollection)result).AddSegment(segment, ref missing, ref missing);

            return(result);
        }
        private static ExceptionObject CreateExceptionObject(int id,
                                                             [NotNull] IGeometry geometry)
        {
            Box box = QaGeometryUtils.CreateBox(geometry);

            return(new ExceptionObject(id, new Guid(), new Guid(),
                                       box, 0.001,
                                       geometry.GeometryType,
                                       ShapeMatchCriterion.EqualEnvelope,
                                       "Issue.Code", "SHAPE",
                                       new InvolvedTable[] { }));
        }
Exemple #20
0
        private static double GetDistanceToVertices([NotNull] IPoint point,
                                                    [NotNull] IFeature neighbourFeature,
                                                    [NotNull] IPoint nearestPoint,
                                                    double maxNeededDistance)
        {
            double minDistance2 = double.MaxValue;

            SegmentProxy nearestSegment = null;
            var          isEndNearest   = false;
            Pnt          qaPoint        = QaGeometryUtils.CreatePoint3D(point);

            IEnumerable <SegmentProxy> segments = EnumSegments(qaPoint, neighbourFeature,
                                                               maxNeededDistance);

            foreach (SegmentProxy segment in segments)
            {
                if (GetNearest(qaPoint, segment.GetStart(false), ref minDistance2))
                {
                    nearestSegment = segment;
                    isEndNearest   = false;
                }

                if (GetNearest(qaPoint, segment.GetEnd(false), ref minDistance2))
                {
                    nearestSegment = segment;
                    isEndNearest   = true;
                }
            }

            double minDistance;

            if (nearestSegment != null)
            {
                minDistance = Math.Sqrt(minDistance2);

                if (minDistance <= maxNeededDistance)
                {
                    Pnt nearest = !isEndNearest
                                                              ? nearestSegment.GetStart(true)
                                                              : nearestSegment.GetEnd(true);

                    nearestPoint.PutCoords(nearest.X, nearest.Y);
                    nearestPoint.Z = nearest[2];
                }
            }
            else
            {
                minDistance = double.MaxValue;
            }

            return(minDistance);
        }
Exemple #21
0
        private void ValidateTri(List <WKSPointZ> wksPointZs, bool isDefined)
        {
            List <Pnt> points =
                wksPointZs.Select(wksPointZ => QaGeometryUtils.CreatePoint3D(wksPointZ)).ToList();

            var pointsWithoutEndPoint = new List <Pnt>(points);

            pointsWithoutEndPoint.RemoveAt(points.Count - 1);

            Plane plane = QaGeometryUtils.CreatePlane(pointsWithoutEndPoint);

            Assert.True(plane.IsDefined == isDefined);
        }
            public override IEnumerable <Proximity> GetProximities(Pnt point,
                                                                   bool as3D,
                                                                   IBox box)
            {
                foreach (WKSPointZ wksPoint in _wksPoints)
                {
                    Pnt part = QaGeometryUtils.CreatePoint3D(wksPoint);

                    if (box.Contains((IPnt)part))
                    {
                        yield return(new PointProximity(point, as3D, part));
                    }
                }
            }
            GetPerpendicularSegmentPairs()
            {
                for (var baseIndex = 0; baseIndex < _sortedHorizontalSegments.Count; baseIndex++)
                {
                    AzimuthSegment baseSegment = _sortedHorizontalSegments[baseIndex];

                    double baseAzimuth = baseSegment.Azimuth;

                    WKSPointZ baseStart =
                        QaGeometryUtils.GetWksPoint(baseSegment.Segment.GetStart(true));

                    WKSPointZ baseEnd =
                        QaGeometryUtils.GetWksPoint(baseSegment.Segment.GetEnd(true));

                    double exactPerpendicularAzimuth = baseAzimuth + Math.PI / 2;
                    double minSearchAzimuth          = exactPerpendicularAzimuth - NearAngleRad;
                    double maxSearchAzimuth          = exactPerpendicularAzimuth + NearAngleRad;

                    for (int perpendicularIndex = baseIndex + 1;
                         perpendicularIndex < _sortedHorizontalSegments.Count;
                         perpendicularIndex++)
                    {
                        AzimuthSegment candidate = _sortedHorizontalSegments[perpendicularIndex];

                        if (candidate.Azimuth <= minSearchAzimuth)
                        {
                            continue;
                        }

                        if (candidate.Azimuth >= maxSearchAzimuth)
                        {
                            break;
                        }

                        WKSPointZ candidateStart =
                            QaGeometryUtils.GetWksPoint(candidate.Segment.GetStart(true));

                        WKSPointZ candidateEnd =
                            QaGeometryUtils.GetWksPoint(candidate.Segment.GetEnd(true));

                        if (IsConnected(baseStart, candidateStart) ||
                            IsConnected(baseStart, candidateEnd) ||
                            IsConnected(baseEnd, candidateStart) ||
                            IsConnected(baseEnd, candidateEnd))
                        {
                            yield return(new PerpendicularSegmentPair(baseSegment, candidate));
                        }
                    }
                }
            }
Exemple #24
0
            protected IIndexedMultiPatch GetIndexedMultipatch(
                [NotNull] IFeature multiPatchFeature)
            {
                Assert.ArgumentNotNull(multiPatchFeature, nameof(multiPatchFeature));

                var indexedMultiPatchFeature =
                    multiPatchFeature as IIndexedMultiPatchFeature;

                IIndexedMultiPatch result =
                    indexedMultiPatchFeature != null && _alternateSpatialReference == null
                                                ? indexedMultiPatchFeature.IndexedMultiPatch
                                                : QaGeometryUtils.CreateIndexedMultiPatch(
                        GetMultiPatch(multiPatchFeature));

                return(result);
            }
Exemple #25
0
            protected override IIndexedMultiPatch GetAdaptedMultiPatch()
            {
                IMultiPatch multiPatch       = GetMultiPatch(_multiPatchFeature);
                var         parts            = (IGeometryCollection)multiPatch;
                var         outerRingIndexes = new List <int>();

                int partCount = parts.GeometryCount;

                for (int partIndex = 0; partIndex < partCount; partIndex++)
                {
                    var ring = parts.Geometry[partIndex] as IRing;
                    if (ring == null)
                    {
                        continue;
                    }

                    bool isBeginning = false;
                    multiPatch.GetRingType(ring, ref isBeginning);

                    if (!isBeginning)
                    {
                        continue;
                    }

                    int followingRings = multiPatch.FollowingRingCount[ring];
                    if (followingRings <= 0)
                    {
                        continue;
                    }

                    if (!IsHorizontal(ring))
                    {
                        continue;
                    }

                    outerRingIndexes.Add(partIndex);
                }

                if (outerRingIndexes.Count > 0)
                {
                    IMultiPatch adapted =
                        CopyWithConvertedInnerRings(multiPatch, outerRingIndexes);
                    return(QaGeometryUtils.CreateIndexedMultiPatch(adapted));
                }

                return(GetIndexedMultipatch(_multiPatchFeature));
            }
Exemple #26
0
        public void IsPlaneVerticalTest()
        {
            var construction = new MultiPatchConstruction();

            construction.StartRing(0, 0, 0)
            .Add(5, 0, 0)
            .Add(5, 0, 5)
            .Add(0, 0, 5);
            IMultiPatch        multiPatch        = construction.MultiPatch;
            IIndexedMultiPatch indexedMultiPatch =
                QaGeometryUtils.CreateIndexedMultiPatch(multiPatch);

            Plane     plane  = QaGeometryUtils.CreatePlane(indexedMultiPatch.GetSegments());
            WKSPointZ normal = plane.GetNormalVector();

            Assert.AreEqual(0, normal.Z);
        }
        IPolyline ITopologicalLine.GetLine()
        {
            if (PartIndex < 0)
            {
                return(FullLine);
            }

            if (((IGeometryCollection)FullLine).GeometryCount <= 1)
            {
                return(FullLine);
            }

            IPolyline line = QaGeometryUtils.CreatePolyline(Path);

            ((ISegmentCollection)line).AddSegmentCollection(
                (ISegmentCollection)GeometryFactory.Clone(Path));
            return(line);
        }
Exemple #28
0
        public void CanProjectToPlaneTest()
        {
            var construction = new MultiPatchConstruction();

            construction.StartRing(0, 0, 0)
            .Add(5, 0, 0)
            .Add(5, 0, 5)
            .Add(0, 0, 5);
            IMultiPatch        multiPatch        = construction.MultiPatch;
            IIndexedMultiPatch indexedMultiPatch =
                QaGeometryUtils.CreateIndexedMultiPatch(multiPatch);

            IList <Pnt>       points    = QaGeometryUtils.GetPoints(indexedMultiPatch.GetSegments());
            Plane             plane     = QaGeometryUtils.CreatePlane(points);
            IList <WKSPointZ> projected = QaGeometryUtils.ProjectToPlane(plane, points);

            ValidateForm(indexedMultiPatch, projected);
        }
            public override VerticalFace ReadFace()
            {
                _latestPartSegments = null;

                if (!_enumValid)
                {
                    return(null);
                }

                int currentPart  = Assert.NotNull(_segmentsEnum.Current).PartIndex;
                int segmentCount = _indexedSegments.GetPartSegmentCount(currentPart);

                var partSegments = new List <SegmentProxy>(segmentCount)
                {
                    _segmentsEnum.Current
                };

                if (_segmentsEnum.Current == null)
                {
                    return(null);
                }

                double zMin = _segmentsEnum.Current.GetStart(true)[2];
                double zMax = zMin;

                while ((_enumValid = _segmentsEnum.MoveNext()) &&
                       Assert.NotNull(_segmentsEnum.Current).PartIndex == currentPart)
                {
                    partSegments.Add(_segmentsEnum.Current);

                    if (_segmentsEnum.Current != null)
                    {
                        double z = _segmentsEnum.Current.GetStart(true)[2];
                        zMin = Math.Min(z, zMin);
                        zMax = Math.Max(z, zMax);
                    }
                }

                Plane plane = QaGeometryUtils.CreatePlane((IEnumerable <SegmentProxy>)partSegments);

                _latestPartSegments = partSegments;

                return(new VerticalFace(plane, zMax - zMin));
            }
        private ParallelSegmentPairProvider GetParallelSegmentPairProvider(
            [NotNull] IFeature feature)
        {
            var indexedFeature            = feature as IIndexedMultiPatchFeature;
            IIndexedMultiPatch multiPatch = indexedFeature?.IndexedMultiPatch ??
                                            QaGeometryUtils.CreateIndexedMultiPatch(
                (IMultiPatch)feature.Shape);

            if (_perRing)
            {
                return(new RingParallelSegmentPairProvider(_nearAngleRad,
                                                           _horizontalToleranceRad,
                                                           _xyResolution, multiPatch));
            }

            return(new MultipatchParallelSegmentPairProvider(_nearAngleRad,
                                                             _horizontalToleranceRad,
                                                             _xyResolution, multiPatch));
        }