private int CheckConstraint([NotNull] IFeature upperFeature, int upperTableIndex,
                                    [NotNull] IFeature lowerFeature, int lowerTableIndex,
                                    [NotNull] IPoint intersectionPoint,
                                    double zDifference)
        {
            string conditionMessage;
            bool   fulFilled = IsZRelationConditionFulfilled(
                upperFeature, upperTableIndex,
                lowerFeature, lowerTableIndex,
                zDifference,
                out conditionMessage);

            if (fulFilled)
            {
                return(NoError);
            }

            string message = $"Z distance = {zDifference:N2}; {conditionMessage}";

            return(ErrorReporting.Report(
                       message, intersectionPoint,
                       Codes[Code.ConstraintNotFulfilled],
                       TestUtils.GetShapeFieldNames(upperFeature, lowerFeature),
                       upperFeature, lowerFeature));
        }
 private int ValidateZNotNull([NotNull] ZRangeFeature feature)
 {
     return(double.IsNaN(feature.ZMin) || double.IsNaN(feature.ZMax)
                                ? ErrorReporting.Report("Z is NaN", feature.Shape,
                                                        Codes[Code.UndefinedZ],
                                                        TestUtils.GetShapeFieldName(
                                                            feature.Feature),
                                                        feature.Feature)
                                : 0);
 }
 private int HandleNonPlanarError([NotNull] NonPlanarError nonPlanarError,
                                  [NotNull] IFeature planarFeature)
 {
     return(_ignoreNonCoplanarReferenceRings
                                ? NoError
                                : ErrorReporting.Report(
                nonPlanarError.Message,
                nonPlanarError.SegmentsPlane.Geometry,
                Codes[Code.FaceNotCoplanar],
                ((IFeatureClass)planarFeature.Class).ShapeFieldName,
                new object[] { nonPlanarError.MaximumOffset },
                planarFeature));
 }
        private int CheckConstraint([NotNull] ZRangeFeature minFeature,
                                    [NotNull] ZRangeFeature maxFeature,
                                    [NotNull] IntersectionGeometryProvider geometryProvider,
                                    double zDifference)
        {
            string conditionMessage;
            bool   fulFilled = IsZRelationConditionFulfilled(
                maxFeature.Feature, maxFeature.TableIndex,
                minFeature.Feature, minFeature.TableIndex,
                zDifference,
                out conditionMessage);

            if (fulFilled)
            {
                return(NoError);
            }

            IGeometry errorGeometry = geometryProvider.Geometry;

            return(ErrorReporting.Report(conditionMessage, errorGeometry,
                                         Codes[Code.ConstraintNotFulfilled], null,
                                         maxFeature.Feature,
                                         minFeature.Feature));
        }
        protected override int ReportErrors(IFeature feature1, int tableIndex1,
                                            IFeature feature2, int tableIndex2)
        {
            var zRangeFeature1 =
                new ZRangeFeature(feature1, tableIndex1, _envelopeTemplate);
            var zRangeFeature2 =
                new ZRangeFeature(feature2, tableIndex2, _envelopeTemplate);

            var errorCount            = 0;
            int errorCountPreZNotNull = errorCount;

            errorCount += ValidateZNotNull(zRangeFeature1);
            errorCount += ValidateZNotNull(zRangeFeature2);

            if (errorCount != errorCountPreZNotNull)
            {
                // one or both Z values are NaN
                return(errorCount);
            }

            ZRangeFeature minFeature;
            ZRangeFeature maxFeature;

            if (zRangeFeature1.ZMin <= zRangeFeature2.ZMin)
            {
                minFeature = zRangeFeature1;
                maxFeature = zRangeFeature2;
            }
            else
            {
                minFeature = zRangeFeature2;
                maxFeature = zRangeFeature1;
            }

            double minimumZDifference =
                GetMinimumZDifference(minFeature.Feature, minFeature.TableIndex,
                                      maxFeature.Feature, maxFeature.TableIndex);
            double maximumZDifference =
                GetMaximumZDifference(minFeature.Feature, minFeature.TableIndex,
                                      maxFeature.Feature, maxFeature.TableIndex);

            double dz = maxFeature.ZMin - minFeature.ZMax;

            var geometryProvider =
                new IntersectionGeometryProvider(minFeature, maxFeature);

            if (minimumZDifference > 0 && dz < minimumZDifference)
            {
                string    description;
                IssueCode issueCode;
                if (dz > 0)
                {
                    issueCode   = Codes[Code.TooSmall];
                    description = string.Format(
                        "The Z distance between the feature Z ranges is too small ({0})",
                        FormatComparison(dz, minimumZDifference, "<"));
                }
                else
                {
                    double overlapDistance = Math.Min(minFeature.ZMax, maxFeature.ZMax) -
                                             Math.Max(minFeature.ZMin, maxFeature.ZMin);

                    issueCode   = Codes[Code.RangeOverlap];
                    description = $"The feature Z ranges overlap by {overlapDistance:N2}";
                }

                errorCount += ErrorReporting.Report(description,
                                                    geometryProvider.Geometry,
                                                    issueCode, null,
                                                    minFeature.Feature,
                                                    maxFeature.Feature);
            }

            if (maximumZDifference > 0 && dz > maximumZDifference)
            {
                // a z difference larger than maximum is always an error
                string description = string.Format(
                    "The Z distance between the feature Z ranges is too large ({0})",
                    FormatComparison(dz, maximumZDifference, ">"));

                errorCount += ErrorReporting.Report(
                    description,
                    geometryProvider.Geometry, Codes[Code.TooLarge],
                    TestUtils.GetShapeFieldName(feature1),
                    new object[] { dz },
                    feature1, feature2);
            }

            errorCount += CheckConstraint(minFeature, maxFeature, geometryProvider, dz);

            return(errorCount);
        }
        private int CheckIntersection([NotNull] IPoint intersectionPoint,
                                      double feature2Z,
                                      double?dZ,
                                      [NotNull] IFeature feature1, int tableIndex1,
                                      [NotNull] IFeature feature2, int tableIndex2)
        {
            double feature1Z = intersectionPoint.Z;

            if (double.IsNaN(feature1Z))
            {
                return(IgnoreUndefinedZValues
                                               ? NoError
                                               : ErrorReporting.Report("Z is NaN", intersectionPoint,
                                                                       Codes[Code.UndefinedZ],
                                                                       TestUtils.GetShapeFieldName(feature1),
                                                                       feature1, feature2));
            }

            //double feature2Z = GeometryUtils.GetZValueFromGeometry(
            //	feature2.Shape, intersectionPoint,
            //	GeometryUtils.GetXyTolerance(feature2));

            if (double.IsNaN(feature2Z))
            {
                return(NoError);
            }

            double dz = dZ ?? Math.Abs(feature1Z - feature2Z);

            double minimumZDifference;
            double maximumZDifference;

            GetValidZDifferenceInterval(feature1, tableIndex1,
                                        feature2, tableIndex2,
                                        feature1Z, feature2Z,
                                        out minimumZDifference, out maximumZDifference);

            int errorCount = 0;

            if (minimumZDifference > 0 && dz < minimumZDifference)
            {
                // a z difference smaller than the minimum is always an error
                errorCount += ErrorReporting.Report(
                    string.Format("The Z distance is too small ({0})",
                                  FormatComparison(dz, minimumZDifference, "<")),
                    intersectionPoint,
                    Codes[Code.TooSmall],
                    TestUtils.GetShapeFieldName(feature1),
                    new object[] { dz },
                    feature1, feature2);
            }

            if (maximumZDifference > 0 && dz > maximumZDifference)
            {
                // a z difference larger than the maximum is always an error
                errorCount += ErrorReporting.Report(
                    string.Format("The Z distance is too large ({0})",
                                  FormatComparison(dz, maximumZDifference, ">")),
                    intersectionPoint,
                    Codes[Code.TooLarge],
                    TestUtils.GetShapeFieldName(feature1),
                    new object[] { dz },
                    feature1, feature2);
            }

            return(errorCount +
                   (feature1Z >= feature2Z
                                        ? CheckConstraint(feature1, tableIndex1,
                                                          feature2, tableIndex2,
                                                          intersectionPoint, dz)
                                        : CheckConstraint(feature2, tableIndex2,
                                                          feature1, tableIndex1,
                                                          intersectionPoint, dz)));
        }