public static int ReportDuplicates( [NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [NotNull] IErrorReporting errorReporting, [CanBeNull] IssueCode issueCode, [CanBeNull] IValidRelationConstraint validRelationConstraint) { Assert.ArgumentNotNull(row1, nameof(row1)); Assert.ArgumentNotNull(row2, nameof(row2)); Assert.ArgumentNotNull(errorReporting, nameof(errorReporting)); string errorDescription; if (!AreDuplicates(row1, tableIndex1, row2, tableIndex2, validRelationConstraint, out errorDescription)) { return(_noError); } IGeometry errorGeometry = ((IFeature)row1).ShapeCopy; const bool reportIndividualParts = false; return(errorReporting.Report(errorDescription, errorGeometry, issueCode, reportIndividualParts, row1, row2)); }
public static bool AreDuplicates( [NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [CanBeNull] IValidRelationConstraint validRelationConstraint, [NotNull] out string errorDescription) { Assert.ArgumentNotNull(row1, nameof(row1)); Assert.ArgumentNotNull(row2, nameof(row2)); if (row1 == row2) { errorDescription = string.Empty; return(false); } IGeometry g1 = ((IFeature)row1).Shape; IGeometry g2 = ((IFeature)row2).Shape; // equal if all corresponding vertices are within xy tolerance - z is ignored if (!GeometryUtils.AreEqualInXY(g1, g2)) { errorDescription = string.Empty; return(false); } return(!HasFulfilledConstraint(row1, tableIndex1, row2, tableIndex2, validRelationConstraint, "Geometries are equal", out errorDescription)); }
private static bool HasFulfilledConstraint( [NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [CanBeNull] IValidRelationConstraint validRelationConstraint, [NotNull] string message, [NotNull] out string formattedMessage) { Assert.ArgumentNotNull(row1, nameof(row1)); Assert.ArgumentNotNull(row2, nameof(row2)); Assert.ArgumentNotNullOrEmpty(message, nameof(message)); if (validRelationConstraint == null || !validRelationConstraint.HasConstraint) { formattedMessage = message; return(false); } string conditionMessage; if (validRelationConstraint.IsFulfilled(row1, tableIndex1, row2, tableIndex2, out conditionMessage)) { formattedMessage = string.Empty; return(true); } formattedMessage = $"{message} and constraint is not fulfilled: {conditionMessage}"; return(false); }
private int ReportError([NotNull] IFeature pointFeature, [NotNull] IFeature referenceFeature, [NotNull] IPoint point, [NotNull] IPoint nearPoint, double distance, double minimumDistance, bool isWithinPolygon, GeometryComponent geometryComponent, [CanBeNull] IValidRelationConstraint validConstraint) { IssueCode issueCode; string description; IGeometry errorGeometry; if (isWithinPolygon) { description = "Point lies within polygon"; errorGeometry = GeometryFactory.Clone(point); issueCode = validConstraint == null ? Codes[Code.PointWithin] : Codes[Code.PointWithin_ConstraintNotFulfilled]; } else { if (geometryComponent == GeometryComponent.EntireGeometry) { description = string.Format( "Point is too close to reference feature: {0}", FormatLengthComparison(distance, "<", minimumDistance, _spatialReference)); } else { description = string.Format( "Point is too close to {0} of reference feature: {1}", GeometryComponentUtils.GetDisplayText(geometryComponent), FormatLengthComparison(distance, "<", minimumDistance, _spatialReference)); } bool reportAsConnectionLine = MinimumErrorLineLength >= 0 && distance >= MinimumErrorLineLength; errorGeometry = GetErrorGeometry(point, nearPoint, reportAsConnectionLine); issueCode = validConstraint == null ? Codes[Code.PointTooClose] : Codes[Code.PointTooClose_ConstraintNotFulfilled]; } return(ReportError(description, errorGeometry, issueCode, _shapeFieldName, pointFeature, referenceFeature)); }
public static int ReportIntersections( [NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [NotNull] IErrorReporting errorReporting, [CanBeNull] IssueCode issueCode, [CanBeNull] IValidRelationConstraint validRelationConstraint, bool reportIndividualParts, [CanBeNull] GeometryConstraint validIntersectionGeometryConstraint = null, GeometryComponent geomComponent1 = GeometryComponent.EntireGeometry, GeometryComponent geomComponent2 = GeometryComponent.EntireGeometry) { Assert.ArgumentNotNull(row1, nameof(row1)); Assert.ArgumentNotNull(row2, nameof(row2)); Assert.ArgumentNotNull(errorReporting, nameof(errorReporting)); if (row1 == row2) { return(_noError); } string errorDescription; if (HasFulfilledConstraint(row1, tableIndex1, row2, tableIndex2, validRelationConstraint, "Features intersect", out errorDescription)) { return(_noError); } IGeometry shape1 = ((IFeature)row1).Shape; IGeometry shape2 = ((IFeature)row2).Shape; var g1 = GeometryComponentUtils.GetGeometryComponent(shape1, geomComponent1); var g2 = GeometryComponentUtils.GetGeometryComponent(shape2, geomComponent2); var errorCount = 0; if (g1 != null && g2 != null) { foreach (IGeometry errorGeometry in IntersectionUtils.GetAllIntersections(g1, g2)) { if (validIntersectionGeometryConstraint == null || !validIntersectionGeometryConstraint.IsFulfilled(errorGeometry)) { errorCount += errorReporting.Report(errorDescription, errorGeometry, issueCode, reportIndividualParts, row1, row2); } } } return(errorCount); }
protected override int FindErrors(IRow row1, int tableIndex1, IRow row2, int tableIndex2) { var feature1 = row1 as IFeature; var feature2 = row2 as IFeature; if (feature1 == null || feature2 == null) { return(NoError); } if (!_vertexCoincidenceChecker.VerifyWithinFeature && (feature1 == feature2)) { return(NoError); } if (_allowedNonCoincidenceConditionSql != null && (feature1 != feature2)) { if (_allowedNonCoincidenceCondition == null) { const bool constraintIsDirected = false; _allowedNonCoincidenceCondition = new ValidRelationConstraint( _allowedNonCoincidenceConditionSql, constraintIsDirected, GetSqlCaseSensitivity()); } string conditionMessage; if (_allowedNonCoincidenceCondition.IsFulfilled(row1, tableIndex1, row2, tableIndex2, out conditionMessage)) { // non-coincidence is allowed between these two features return(NoError); } } if (_pointsEnumerator == null || _pointsEnumerator.Feature != feature1) { _pointsEnumerator = PointsEnumeratorFactory.Create(feature1, _pointSearchEnvelope); } return(_vertexCoincidenceChecker.CheckCoincidence(_pointsEnumerator, feature2)); }
protected override int FindErrors(IRow row1, int tableIndex1, IRow row2, int tableIndex2) { if (_validRelationConstraint == null) { const bool constraintIsDirected = true; _validRelationConstraint = new ValidRelationConstraint( _validRelationConstraintSql, constraintIsDirected, GetSqlCaseSensitivity()); } return(QaSpatialRelationUtils.ReportTouches(row1, tableIndex1, row2, tableIndex2, this, GetIssueCode(), _validRelationConstraint, _validTouchGeometryConstraint, reportIndividualParts: true)); }
protected override int FindErrors(IRow row1, int tableIndex1, IRow row2, int tableIndex2) { if (_validRelationConstraint == null) { const bool constraintIsDirected = true; _validRelationConstraint = new ValidRelationConstraint( _validRelationConstraintSql, constraintIsDirected, GetSqlCaseSensitivity()); } return(QaSpatialRelationUtils.ReportIntersections( row1, tableIndex1, row2, tableIndex2, this, GetIssueCode(), _validRelationConstraint, !ReportIntersectionsAsMultipart, _validIntersectionGeometryConstraint)); }
public static int ReportOverlaps( [NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [NotNull] IErrorReporting errorReporting, [CanBeNull] IssueCode issueCode, [CanBeNull] IValidRelationConstraint validRelationConstraint, bool reportIndividualParts) { Assert.ArgumentNotNull(row1, nameof(row1)); Assert.ArgumentNotNull(row2, nameof(row2)); Assert.ArgumentNotNull(errorReporting, nameof(errorReporting)); if (row1 == row2) { return(_noError); } IGeometry g1 = ((IFeature)row1).Shape; IGeometry g2 = ((IFeature)row2).Shape; string errorDescription; if (HasFulfilledConstraint(row1, tableIndex1, row2, tableIndex2, validRelationConstraint, "Features overlap", out errorDescription)) { return(_noError); } IGeometry intersection = TestUtils.GetOverlap(g1, g2); if (intersection.IsEmpty) { Marshal.ReleaseComObject(intersection); return(_noError); } return(errorReporting.Report(errorDescription, intersection, issueCode, reportIndividualParts, row1, row2)); }
protected override int FindErrors(IRow row1, int tableIndex1, IRow row2, int tableIndex2) { if (_validRelationConstraint == null) { const bool constraintIsDirected = true; _validRelationConstraint = new ValidRelationConstraint( _validRelationConstraintSql, constraintIsDirected, GetSqlCaseSensitivity()); } const bool reportIndividualErrors = false; return(QaSpatialRelationUtils.ReportOverlaps(row1, tableIndex1, row2, tableIndex2, this, GetIssueCode(), _validRelationConstraint, reportIndividualErrors)); }
protected override int FindErrors(IRow row1, int tableIndex1, IRow row2, int tableIndex2) { if (_validRelationConstraint == null) { const bool constraintIsDirected = false; _validRelationConstraint = new ValidRelationConstraint( _validRelationConstraintSql, constraintIsDirected, GetSqlCaseSensitivity()); } if (!_reportSingleErrorPerDuplicateSet) { return(QaSpatialRelationUtils.ReportDuplicates(row1, tableIndex1, row2, tableIndex2, this, GetIssueCode(), _validRelationConstraint)); } int oid1 = row1.OID; int oid2 = row2.OID; if (!IsKnownDuplicate(oid1, oid2)) { string errorDescription; if (QaSpatialRelationUtils.AreDuplicates( row1, tableIndex1, row2, tableIndex2, _validRelationConstraint, out errorDescription)) { AddDuplicate(oid1, oid2); } } // duplicates will be reported at end return(NoError); }
private bool HasFulfilledConstraint([NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [NotNull] string description, [NotNull] out string formattedMessage) { // TODO consider consolidating with QaSpatialRelationUtils.HasFulfilledConstraint() if (_validRelationConstraintSql == null) { formattedMessage = description; return(false); } if (_validRelationConstraint == null) { const bool constraintIsDirected = false; _validRelationConstraint = new ValidRelationConstraint(_validRelationConstraintSql, constraintIsDirected, GetSqlCaseSensitivity()); } string conditionMessage; if (_validRelationConstraint.IsFulfilled(row1, tableIndex1, row2, tableIndex2, out conditionMessage)) { formattedMessage = string.Empty; return(true); } formattedMessage = string.Format("{0} and constraint is not fulfilled: {1}", description, conditionMessage); return(false); }
private int CheckTable([NotNull] IFeature feature, [NotNull] IFeatureClass referenceClass, int referenceClassIndex) { GeometryComponent geometryComponent = GetGeometryComponent(referenceClassIndex); IValidRelationConstraint validConstraint = GetValidRelationConstraint(referenceClassIndex); if (_pointTemplate == null) { _pointTemplate = new PointClass(); } var errorCount = 0; foreach (IPoint point in GetNodes(feature.Shape, _pointTemplate)) { ISpatialFilter filter = PrepareSpatialFilter(point, referenceClassIndex); QueryFilterHelper helper = _helper[referenceClassIndex]; const int pointClassIndex = 0; foreach (IRow referenceRow in Search((ITable)referenceClass, filter, helper, point)) { if (TestUtils.IsSameRow(feature, referenceRow)) { continue; } var referenceFeature = (IFeature)referenceRow; string conditionMessage; if (validConstraint != null && validConstraint.HasConstraint && validConstraint.IsFulfilled(feature, pointClassIndex, referenceFeature, referenceClassIndex, out conditionMessage)) { continue; } double standardDistance; double?rightSideDistance; double maxNeededDistance = GetMaxNeededDistance( feature, referenceFeature, referenceClassIndex, out standardDistance, out rightSideDistance); maxNeededDistance = Math.Max(maxNeededDistance, _pointClassXyTolerance); bool isWithinPolygon; bool onRightSide; double distance = GetDistance(point, referenceFeature, _nearPoint, geometryComponent, maxNeededDistance, out isWithinPolygon, out onRightSide); if (AllowCoincidentPoints && IsSmallerThanXyTolerance(distance, referenceClassIndex)) { continue; } if (distance > maxNeededDistance) { continue; } double minimumDistance = maxNeededDistance; if (rightSideDistance.HasValue) { if (_referenceFlipConditions == null) { _referenceFlipConditions = CreateFlipConditions(_referenceFlipExpressions); } bool flip = _referenceFlipConditions.Count > 0 ? _referenceFlipConditions[ referenceClassIndex - _firstReferenceClassIndex].IsFulfilled( referenceFeature) : false; double useDistance = (onRightSide == flip) ? standardDistance : rightSideDistance.Value; if (distance > useDistance) { continue; } minimumDistance = useDistance; } errorCount += ReportError(feature, referenceFeature, point, _nearPoint, distance, minimumDistance, isWithinPolygon, geometryComponent, validConstraint); } } return(errorCount); }
public static int ReportCrossings( [NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [NotNull] IErrorReporting errorReporting, [CanBeNull] IssueCode issueCode, [CanBeNull] IValidRelationConstraint validRelationConstraint, bool reportIndividualParts) { Assert.ArgumentNotNull(row1, nameof(row1)); Assert.ArgumentNotNull(row2, nameof(row2)); Assert.ArgumentNotNull(errorReporting, nameof(errorReporting)); if (row1 == row2) { return(_noError); } IGeometry g1 = ((IFeature)row1).Shape; IGeometry g2 = ((IFeature)row2).Shape; string errorDescription; if (HasFulfilledConstraint(row1, tableIndex1, row2, tableIndex2, validRelationConstraint, "Features cross", out errorDescription)) { return(_noError); } var errorCount = 0; foreach (IGeometry errorGeometry in GetCrossings(g1, g2)) { if (errorGeometry.IsEmpty) { continue; } errorCount += errorReporting.Report(errorDescription, errorGeometry, issueCode, reportIndividualParts, row1, row2); } return(errorCount); //const bool overlap = false; //IGeometry intersection = TestUtils.GetIntersection(g1, g2, overlap); //// TODO remove boundary //try //{ // if (intersection.IsEmpty) // { // return _noError; // } // return errorReporting.Report("Features cross", // intersection, reportIndividualParts, // row1, row2); //} //finally //{ // Marshal.ReleaseComObject(intersection); //} }
public static int ReportTouches( [NotNull] IRow row1, int tableIndex1, [NotNull] IRow row2, int tableIndex2, [NotNull] IErrorReporting errorReporting, [CanBeNull] IssueCode issueCode, [CanBeNull] IValidRelationConstraint validRelationConstraint, [CanBeNull] GeometryConstraint validTouchGeometryConstraint, bool reportIndividualParts = false) { Assert.ArgumentNotNull(row1, nameof(row1)); Assert.ArgumentNotNull(row2, nameof(row2)); Assert.ArgumentNotNull(errorReporting, nameof(errorReporting)); if (row1 == row2) { return(_noError); } IGeometry g1 = ((IFeature)row1).Shape; IGeometry g2 = ((IFeature)row2).Shape; string errorDescription; if (HasFulfilledConstraint(row1, tableIndex1, row2, tableIndex2, validRelationConstraint, "Geometries touch", out errorDescription)) { return(_noError); } var errorCount = 0; foreach (IGeometry geometry in GetTouches(g1, g2)) { if (geometry.IsEmpty) { continue; } if (reportIndividualParts) { foreach (IGeometry part in GeometryUtils.Explode(geometry)) { if (part.IsEmpty || validTouchGeometryConstraint != null && validTouchGeometryConstraint.IsFulfilled(part)) { continue; } errorCount += errorReporting.Report(errorDescription, part, issueCode, false, // already exploded row1, row2); } } else { if (validTouchGeometryConstraint != null && validTouchGeometryConstraint.IsFulfilled(geometry)) { continue; } errorCount += errorReporting.Report(errorDescription, geometry, issueCode, false, row1, row2); } } return(errorCount); }