private static IEnumerable <esriMonotinicityEnum> GetInvalidMonotonicityTypes( [NotNull] IPolyline polyline) { esriMonotinicityEnum trend = MeasureUtils.GetMonotonicityTrend(polyline); switch (trend) { case esriMonotinicityEnum.esriValueIncreases: yield return(esriMonotinicityEnum.esriValueDecreases); break; case esriMonotinicityEnum.esriValueDecreases: yield return(esriMonotinicityEnum.esriValueIncreases); break; case esriMonotinicityEnum.esriValueLevel: yield return(esriMonotinicityEnum.esriValueIncreases); yield return(esriMonotinicityEnum.esriValueDecreases); break; case esriMonotinicityEnum.esriValuesEmpty: break; default: throw new ArgumentOutOfRangeException(); } }
protected override int ExecuteCore(IRow row, int tableIndex) { if (!_hasM) { return(NoError); } var feature = row as IFeature; if (feature == null) { return(NoError); } var polyline = feature.Shape as IPolyline; if (polyline == null) { return(NoError); } if (_flipCondition == null) { const bool undefinedConstraintIsFulfilled = false; _flipCondition = new RowCondition((ITable)_lineClass, _flipExpression, undefinedConstraintIsFulfilled, GetSqlCaseSensitivity(tableIndex)); } var mAware = (IMAware)polyline; Assert.True(mAware.MAware, "The geometry is not M-aware"); IEnumerable <MMonotonicitySequence> errorSequences = MeasureUtils.GetErrorSequences( polyline, _expectedMonotonicity, () => _flipCondition.IsFulfilled(feature), _allowConstantValues); return(errorSequences.Sum(errorSequence => ReportError( GetErrorMessage(errorSequence), errorSequence.CreatePolyline(), Codes[Code.MeasuresNotMonotonic], TestUtils.GetShapeFieldName(feature), row))); }
private int ReportInvalidSequence([NotNull] ICollection <ISegment> invalidMSegments, [NotNull] IRow row, double invalidValue) { Assert.ArgumentNotNull(invalidMSegments, nameof(invalidMSegments)); Assert.ArgumentCondition(invalidMSegments.Count > 0, "Empty sequence"); const bool cloneSegments = false; IPolyline errorGeometry = MeasureUtils.GetErrorGeometry(invalidMSegments, cloneSegments); IssueCode issueCode; string errorDescription = GetErrorDescription(invalidValue, invalidMSegments, out issueCode); return(ReportError(errorDescription, errorGeometry, issueCode, _shapeFieldName, row)); }
private int ReportNonUniqueMeasuresWithinFeature([NotNull] IFeature feature) { IGeometry geometry = feature.Shape; if (geometry == null || geometry.IsEmpty) { return(NoError); } var polyline = geometry as IPolyline; if (polyline == null) { return(NoError); } var errorCount = 0; if (MeasureUtils.ContainsAllMonotonicityTypes( polyline, esriMonotinicityEnum.esriValueDecreases, esriMonotinicityEnum.esriValueIncreases)) { IEnumerable <esriMonotinicityEnum> invalidTypes = GetInvalidMonotonicityTypes(polyline); const string description = "Measures are not unique due to non-monotonicity within feature"; errorCount += MeasureUtils.GetMonotonicitySequences(polyline, invalidTypes) .Sum(sequence => ReportError( description, sequence.CreatePolyline(), Codes[Code.MeasuresNotUnique_WithinFeature], TestUtils.GetShapeFieldName(feature), feature)); } return(errorCount); }
private ICollection <InvolvedRow> GetInvolvedRows( [NotNull] OverlappingMeasures overlap, [CanBeNull] out IPolyline lineErrorGeometry, [CanBeNull] out IMultipoint pointErrorGeometry) { Assert.ArgumentNotNull(overlap, nameof(overlap)); var involvedRows = new List <InvolvedRow>(); var polylines = new List <IPolyline>(); var allPoints = new List <IPoint>(); foreach (TestRowReference testRowReference in overlap.Features) { IFeature feature = GetFeature(testRowReference); involvedRows.Add(new InvolvedRow(feature)); var polyline = (IPolyline)feature.Shape; IList <IPoint> points; IPolyline subcurves = MeasureUtils.GetSubcurves(polyline, overlap.MMin, overlap.MMax, out points); allPoints.AddRange(points); if (subcurves != null) { polylines.Add(subcurves); } } lineErrorGeometry = GetErrorGeometry(polylines); pointErrorGeometry = allPoints.Count > 0 ? GeometryFactory.CreateMultipoint(allPoints) : null; return(involvedRows); }
private int CheckFeatures( [NotNull] IEnumerable <KeyValuePair <int, IFeature> > features) { Assert.ArgumentNotNull(features, nameof(features)); var routeMeasures = new RouteMeasures(_mTolerances, _xyTolerances); var errorCount = 0; foreach (KeyValuePair <int, IFeature> pair in features) { int tableIndex = pair.Key; IFeature feature = pair.Value; if (CancelTestingRow(feature)) { continue; } object routeId = feature.Value[_routeIdFieldIndexes[tableIndex]]; if (routeId == null || routeId is DBNull) { continue; } foreach (CurveMeasureRange range in MeasureUtils.GetMeasureRanges(feature, tableIndex)) { routeMeasures.Add(routeId, range); } errorCount += ReportNonUniqueMeasuresWithinFeature(feature); } errorCount += routeMeasures.GetOverlaps().Sum(overlap => ReportOverlap(overlap)); return(errorCount); }
protected virtual bool IsInvalidValue(double m, [NotNull] IRow row, bool isNewRow, [CanBeNull] out string error, [CanBeNull] out IssueCode issueCode) { error = string.Empty; issueCode = null; if (MeasureUtils.IsInvalidValue(m, _invalidValue)) { if (double.IsNaN(_invalidValue)) { issueCode = Codes[Code.UndefinedMValues]; } else { issueCode = Codes[Code.InvalidMValues]; } return(true); } return(false); }
private static IEnumerable <ZMonotonicitySequence> GetErrorSequencesFromSinglePart( [NotNull] IPolyline singlePartPolyline, MonotonicityDirection expectedMonotonicity, [NotNull] Func <bool> isFeatureFlipped, bool allowConstantValues) { bool?featureFlipped = null; var points = (IPointCollection4)singlePartPolyline; int segmentCount = points.PointCount - 1; WKSPointZ[] wksPointZs = new WKSPointZ[points.PointCount]; GeometryUtils.QueryWKSPointZs(points, wksPointZs); ZMonotonicitySequence currentSequence = null; double trend = wksPointZs[segmentCount].Z - wksPointZs[0].Z; esriMonotinicityEnum monotonicityTrend = MeasureUtils.GetMonotonicityType(trend); var checkedMonotonicity = GetCheckedMonotonicityDirection( expectedMonotonicity, monotonicityTrend); esriMonotinicityEnum?preMonotonicity = null; IEnumSegment enumSegments = null; bool?recycling = null; for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) { double dz = wksPointZs[segmentIndex + 1].Z - wksPointZs[segmentIndex].Z; esriMonotinicityEnum monotonicity = MeasureUtils.GetMonotonicityType(dz); if (monotonicity == esriMonotinicityEnum.esriValueDecreases || monotonicity == esriMonotinicityEnum.esriValueIncreases) { if (!featureFlipped.HasValue) { featureFlipped = isFeatureFlipped(); } if (featureFlipped.Value) { monotonicity = monotonicity == esriMonotinicityEnum.esriValueDecreases ? esriMonotinicityEnum.esriValueIncreases : esriMonotinicityEnum.esriValueDecreases; } } if (monotonicity != preMonotonicity) { if (currentSequence != null) { yield return(currentSequence); } preMonotonicity = monotonicity; currentSequence = null; } if (currentSequence == null) { if (monotonicity == esriMonotinicityEnum.esriValueLevel && allowConstantValues) { // ok } else if (monotonicity == esriMonotinicityEnum.esriValueIncreases && checkedMonotonicity == MonotonicityDirection.Increasing) { // ok } else if (monotonicity == esriMonotinicityEnum.esriValueDecreases && checkedMonotonicity == MonotonicityDirection.Decreasing) { // ok } else if (checkedMonotonicity == MonotonicityDirection.Any) { if (monotonicity == esriMonotinicityEnum.esriValueIncreases) { checkedMonotonicity = MonotonicityDirection.Increasing; } else if (monotonicity == esriMonotinicityEnum.esriValueDecreases) { checkedMonotonicity = MonotonicityDirection.Decreasing; } } else { currentSequence = new ZMonotonicitySequence(monotonicity, singlePartPolyline.SpatialReference) { FeatureMonotonicityTrend = monotonicityTrend, FeatureIsFlipped = featureFlipped }; } } if (currentSequence != null) { if (enumSegments == null) { enumSegments = ((ISegmentCollection)singlePartPolyline) .EnumSegments; } var segment = GetSegment(enumSegments, segmentIndex); if (!recycling.HasValue) { recycling = enumSegments.IsRecycling; } currentSequence.Add(recycling.Value ? GeometryFactory.Clone(segment) : segment); if (recycling.Value) { Marshal.ReleaseComObject(segment); } } } if (currentSequence != null) { yield return(currentSequence); } if (enumSegments != null) { enumSegments.Reset(); } }
private int ReportInvalidSegments([NotNull] ISegmentCollection segments, [NotNull] IRow row) { var errorCount = 0; List <ISegment> currentInvalidSequence = null; int currentPartIndex = -1; IEnumSegment enumSegment = segments.EnumSegments; int partIndex = -1; int segmentIndex = -1; ISegment segment; enumSegment.Next(out segment, ref partIndex, ref segmentIndex); while (segment != null) { if (currentInvalidSequence != null && partIndex != currentPartIndex) { // report sequence from previous part errorCount += ReportInvalidSequence(currentInvalidSequence, row, _invalidValue); currentInvalidSequence = null; currentPartIndex = -1; } if (MeasureUtils.HasInvalidMValue(segment, _queryPoint, _invalidValue)) { if (currentInvalidSequence == null) { // initialize sequence currentInvalidSequence = new List <ISegment>(); currentPartIndex = partIndex; } currentInvalidSequence.Add(GeometryFactory.Clone(segment)); } else { if (currentInvalidSequence != null) { errorCount += ReportInvalidSequence(currentInvalidSequence, row, _invalidValue); currentInvalidSequence = null; currentPartIndex = -1; } } // release the segment, otherwise "pure virtual function call" occurs // when there are certain circular arcs (IsLine == true ?) Marshal.ReleaseComObject(segment); enumSegment.Next(out segment, ref partIndex, ref segmentIndex); } if (currentInvalidSequence != null) { // report sequence at end of segment collection errorCount += ReportInvalidSequence(currentInvalidSequence, row, _invalidValue); } return(errorCount); }