예제 #1
0
        public void CanGetBoundaryBoundaryIntersectionLinesAndPoints()
        {
            const string matrixString = "****T****";

            IPolygon g1 = GeometryFactory.CreatePolygon(0, 0, 10, 10, 100);
            IPolygon g2 = GeometryFactory.CreatePolygon(5, 0, 15, 15, 1000);

            g1.SpatialReference = _spatialReference;
            g2.SpatialReference = _spatialReference;

            var matrix = new IntersectionMatrix(matrixString);

            IList <IGeometry> intersections = matrix.GetIntersections(g1, g2);

            WriteGeometries(intersections);

            Assert.AreEqual(2, intersections.Count);

            var polyline = (IPolyline)intersections[0];

            Assert.AreEqual(1, GeometryUtils.GetPartCount(polyline));

            var multipoint = (IMultipoint)intersections[1];

            Assert.AreEqual(1, GeometryUtils.GetPartCount(multipoint));
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(_spatialReference,
                                                         multipoint.SpatialReference));
        }
예제 #2
0
        public void CanGetMultipointPolygonCrossesIntersection()
        {
            var matrix = new IntersectionMatrix("T*T******");

            IMultipoint g1 = GeometryFactory.CreateMultipoint(
                GeometryFactory.CreatePoint(5, 5, 0),
                GeometryFactory.CreatePoint(10, 5, 0),
                GeometryFactory.CreatePoint(15, 5, 0));
            IPolygon g2 = GeometryFactory.CreatePolygon(0, 0, 10, 10, 0);

            g1.SpatialReference = _spatialReference;
            g2.SpatialReference = _spatialReference;

            IList <IGeometry> result12 = matrix.GetIntersections(g1, g2);

            Assert.AreEqual(1, result12.Count);
            Console.WriteLine(GeometryUtils.ToString(result12[0]));
            Assert.AreEqual(2, GeometryUtils.GetPointCount(result12));
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(_spatialReference,
                                                         result12[0].SpatialReference));

            IList <IGeometry> result21 = matrix.GetIntersections(g2, g1);

            Assert.AreEqual(1, result21.Count);
            Console.WriteLine(GeometryUtils.ToString(result21[0]));
            Assert.IsTrue(
                GeometryUtils.AreEqualInXY(result21[0],
                                           g2));                 // can't subtract, same as g2
        }
예제 #3
0
        public void CanCreateBagWithCopies()
        {
            ISpatialReference sref =
                SpatialReferenceUtils.CreateSpatialReference(WellKnownHorizontalCS.LV95);
            IGeometry pt1 = GeometryFactory.CreatePoint(100, 200, 0);
            IGeometry pt2 = GeometryFactory.CreatePoint(100, 200, 0);

            pt1.SpatialReference = sref;

            IGeometryBag bag = GeometryFactory.CreateBag(pt1, pt2);

            var collection = (IGeometryCollection)bag;

            Assert.AreEqual(2, collection.GeometryCount);
            IGeometry bagPt1 = collection.get_Geometry(0);
            IGeometry bagPt2 = collection.get_Geometry(1);

            // expect copies in the bag
            Assert.AreNotEqual(pt1, bagPt1);
            Assert.AreNotEqual(pt2, bagPt2);

            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(sref, bag.SpatialReference, true, true));
            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(sref, bagPt1.SpatialReference, true,
                                               true));
            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(sref, bagPt2.SpatialReference, true,
                                               true));
        }
        public void CanCompareDomainOnlyDifferences()
        {
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              _lv95_xyres_001_zres_001,
                              _lv95_xyres_001_zres_001_largerdomains,
                              true, true, true,               // xy, z, m precisions
                              false, false));                 // tolerances, vcs

            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              _lv95_xyres_001_zres_001,
                              _lv95_xyres_001_zres_001_largerdomains,
                              true, true, true,             // xy, z, m precisions
                              true, true));                 // tolerances, vcs

            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              _lv95_xyres_001_zres_001_largerdomains,
                              _lv95_xyres_001_zres_001,
                              true, true, true,               // xy, z, m precisions
                              false, false));                 // tolerances, vcs

            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              _lv95_xyres_001_zres_001_largerdomains,
                              _lv95_xyres_001_zres_001,
                              true, true, true,             // xy, z, m precisions
                              true, true));                 // tolerances, vcs
        }
        public void CanConvertPolygonToFromShapeMsg()
        {
            string xmlFile = TestData.GetDensifiedWorkUnitPerimeterPath();

            var polygon = (IPolygon)GeometryUtils.FromXmlFile(xmlFile);

            var shapeMsg = ProtobufGeometryUtils.ToShapeMsg(
                polygon, ShapeMsg.FormatOneofCase.EsriShape,
                SpatialReferenceMsg.FormatOneofCase.SpatialReferenceEsriXml);

            IGeometry rehydrated = ProtobufGeometryUtils.FromShapeMsg(shapeMsg);

            Assert.NotNull(rehydrated);
            Assert.IsTrue(GeometryUtils.AreEqual(polygon, rehydrated));
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(polygon.SpatialReference,
                                                         rehydrated.SpatialReference, true, true));

            // ... and WKB
            var wkbWriter = new WkbGeometryWriter();

            byte[] wkb = wkbWriter.WriteGeometry(polygon);

            var wkbShapeMsg = new ShapeMsg()
            {
                Wkb = ByteString.CopyFrom(wkb)
            };

            IGeometry rehydratedFromWkb = ProtobufGeometryUtils.FromShapeMsg(wkbShapeMsg);

            Assert.IsTrue(GeometryUtils.AreEqual(polygon, rehydratedFromWkb));
            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(polygon.SpatialReference,
                                               rehydrated.SpatialReference));

            // ... and envelope
            IEnvelope envelope = polygon.Envelope;

            var envShapeMsg = new ShapeMsg()
            {
                Envelope = new EnvelopeMsg()
                {
                    XMin = envelope.XMin,
                    YMin = envelope.YMin,
                    XMax = envelope.XMax,
                    YMax = envelope.YMax
                },
                SpatialReference = new SpatialReferenceMsg()
                {
                    SpatialReferenceWkid =
                        (int)WellKnownHorizontalCS.LV95
                }
            };

            IEnvelope rehydratedEnvelope =
                (IEnvelope)ProtobufGeometryUtils.FromShapeMsg(envShapeMsg);

            Assert.IsTrue(GeometryUtils.AreEqual(envelope, rehydratedEnvelope));
        }
        public void CanCheckAreEqualCheckCSTypeDifference()
        {
            const bool comparePrecision = true;
            const bool compareVCS       = true;

            Assert.IsFalse(
                SpatialReferenceUtils.AreEqual(_wgs84,
                                               _lv95_xytol_01_ztol_01,
                                               comparePrecision, compareVCS));
        }
        public void CanCheckAreEqualIgnoreXyResolutionDifference()
        {
            const bool comparePrecision = false;
            const bool compareVCS       = true;

            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(_lv95_xyres_001_zres_001,
                                               _lv95_xyres_002_zres_001,
                                               comparePrecision, compareVCS));
        }
        public void CanCheckAreEqualIgnoreXyToleranceDifference()
        {
            const bool comparePrecision = false;
            const bool compareVCS       = true;

            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(_lv95_xytol_01_ztol_01,
                                               _lv95_xytol_02_ztol_01,
                                               comparePrecision, compareVCS));
        }
예제 #9
0
 private static void ValidateSpatialReferences(
     [NotNull] IFeatureClass targetFeatureClass,
     [NotNull] IFeatureClass importFeatureClass)
 {
     if (!SpatialReferenceUtils.AreEqual(
             DatasetUtils.GetSpatialReference(targetFeatureClass),
             DatasetUtils.GetSpatialReference(importFeatureClass),
             comparePrecisionAndTolerance: false,
             compareVerticalCoordinateSystems: false))
     {
         // TODO throw exception
     }
 }
예제 #10
0
        public void CanGetInteriorBoundaryIntersections()
        {
            const string matrixString = "*T*******";

            IPolygon  g1     = GeometryFactory.CreatePolygon(0, 0, 10, 10, 100);
            IPolyline g2line = GeometryFactory.CreatePolyline(
                _spatialReference,
                GeometryFactory.CreatePoint(0, 10, 100),                 // start/endpoint touches polygon
                GeometryFactory.CreatePoint(0, 20, 100),
                GeometryFactory
                .CreatePoint(10, 10, 100),                       // next segment touches the polygon
                GeometryFactory
                .CreatePoint(10, 9, 100),                        // next segment is inside the polygon
                GeometryFactory
                .CreatePoint(6, 9, 100),                         // next segment is partly inside the polygon
                GeometryFactory.CreatePoint(6, 11, 100),
                GeometryFactory.CreatePoint(4, 11, 100),
                GeometryFactory.CreatePoint(4, 10, 100),                 // next segment touches polygon
                GeometryFactory.CreatePoint(2, 10, 100),
                GeometryFactory.CreatePoint(2, 11, 100),
                GeometryFactory.CreatePoint(1, 11, 100),
                GeometryFactory
                .CreatePoint(0, 10, 100));                         // start/endpoint touches polygon

            GeometryUtils.MakeZAware(g2line);

            IPolygon g2 = GeometryFactory.CreatePolygon(g2line);

            GeometryUtils.Simplify(g2);

            g1.SpatialReference = _spatialReference;
            g2.SpatialReference = _spatialReference;

            var matrix = new IntersectionMatrix(matrixString);

            IList <IGeometry> intersections = matrix.GetIntersections(g1, g2);

            WriteGeometries(intersections);

            Assert.AreEqual(1, intersections.Count);

            var polyline = (IPolyline)intersections[0];

            Assert.AreEqual(1, GeometryUtils.GetPartCount(polyline));
            Assert.AreEqual(3, GeometryUtils.GetPointCount(polyline));
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(_spatialReference,
                                                         polyline.SpatialReference));
        }
        public void CanCheckAreEqualCheckXyToleranceIgnoreZToleranceDifference()
        {
            const bool comparePrecision = true;
            const bool compareVCS       = false;

            var watch = new Stopwatch();

            watch.Start();

            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(_lv95_xytol_01_ztol_01,
                                               _lv95lhn95_xytol_01_ztol_02,
                                               comparePrecision, compareVCS));

            Console.WriteLine(@"AreEqual (precision compare): {0:N2} ms",
                              watch.ElapsedMilliseconds);
        }
        public void CanCompareComponents()
        {
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              _lv95lhn95_xytol_01_ztol_02,
                              _lv95ln02_xytol_01_ztol_01,
                              true, true, true,               // xy, z, m precisions
                              false, false));                 // tolerances, vcs

            Assert.IsFalse(SpatialReferenceUtils.AreEqual(_lv95lhn95_xytol_01_ztol_02,
                                                          _lv95ln02_xytol_01_ztol_01,
                                                          true, true, true,
                                                          false, true));

            Assert.IsFalse(SpatialReferenceUtils.AreEqual(_lv95lhn95_xytol_01_ztol_02,
                                                          _lv95ln02_xytol_01_ztol_01,
                                                          true, true, true,
                                                          true, false));
        }
예제 #13
0
        public GeometryComparison([NotNull] IGeometry baseGeometry,
                                  [NotNull] IGeometry compareGeometry,
                                  double xyTolerance, double zTolerance)
        {
            // NOTE: Do not use SpatialReferenceUtils.AreEqual with the parameters
            //       comparePrecisionAndTolerance=true and compareVerticalCoordinateSystems= true because
            //       this also compares M resolution which can differ despite EnsureSpatialReference was called
            //       Additionally, M-comparison is currently not implemented.

            //       A specific comparison method should be provided that compares only the relevant aspects of the spatial reference
            //       -> M-resolution/tolerance only if the geometry is M-aware, etc.
            const bool comparePrecisionAndTolerance     = true;
            const bool compareVerticalCoordinateSystems = false;

            Assert.ArgumentCondition(
                SpatialReferenceUtils.AreEqual(baseGeometry.SpatialReference,
                                               compareGeometry.SpatialReference,
                                               comparePrecisionAndTolerance,
                                               compareVerticalCoordinateSystems),
                "The spatial reference of the base and the compare geometries must be the same.");

            if (GeometryUtils.IsZAware(baseGeometry) &&
                GeometryUtils.IsZAware(compareGeometry))
            {
                Assert.ArgumentCondition(
                    MathUtils.AreEqual(GeometryUtils.GetZResolution(baseGeometry),
                                       GeometryUtils.GetZResolution(compareGeometry)),
                    "The Z-Resolution of the base and the compare geometries must be the same.");
            }

            _baseGeometry    = baseGeometry;
            _compareGeometry = compareGeometry;

            _xyTolerance = xyTolerance;
            _zTolerance  = zTolerance;

            _pointTemplate = new PointClass();
            _pointTemplate.SpatialReference = _baseGeometry.SpatialReference;

            if (!double.IsNaN(_zTolerance))
            {
                SetZTolerance(_pointTemplate, _zTolerance);
            }
        }
        public void CanCompareMinimumComponentsFastEnough()
        {
            Stopwatch watch = Stopwatch.StartNew();
            const int count = 10000;

            for (int i = 0; i < count; i++)
            {
                SpatialReferenceUtils.AreEqual(_lv95lhn95_xytol_01_ztol_02,
                                               _lv95lhn95_xytol_01_ztol_01,
                                               false, false, false,
                                               false, false);
            }

            watch.Stop();
            Console.WriteLine(@"count={0}: {1:N0} ms; per call: {2:N4} ms",
                              count, watch.ElapsedMilliseconds,
                              watch.ElapsedMilliseconds / (double)count);
            Assert.Less((double)watch.ElapsedMilliseconds, 1000);
        }
        public void CanExportToXml()
        {
            IWorkspace workspace = TestUtils.OpenUserWorkspaceOracle();

            IFeatureClass fclass =
                DatasetUtils.OpenFeatureClass(workspace, "TOPGIS_TLM.TLM_STRASSE");

            ISpatialReference spatialReference = ((IGeoDataset)fclass).SpatialReference;

            string xml = SpatialReferenceUtils.ToXmlString(spatialReference);

            Console.WriteLine(xml);

            Assert.IsNotNull(xml);
            Assert.IsNotEmpty(xml);

            ISpatialReference imported = SpatialReferenceUtils.FromXmlString(xml);

            Assert.IsTrue(
                SpatialReferenceUtils.AreEqual(imported, spatialReference));
        }
예제 #16
0
        public void CanGetPolylinePointIntersections()
        {
            const string matrixString = "T********";

            IPoint    g1 = GeometryFactory.CreatePoint(10, 5, 1000);
            IPolyline g2 = GeometryFactory.CreatePolyline(5, 5, 1000, 15, 5, 1000);

            g1.SpatialReference = _spatialReference;
            g2.SpatialReference = _spatialReference;

            var matrix = new IntersectionMatrix(matrixString);

            IList <IGeometry> intersections = matrix.GetIntersections(g1, g2);

            WriteGeometries(intersections);

            Assert.AreEqual(1, intersections.Count);
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(_spatialReference,
                                                         intersections[0]
                                                         .SpatialReference));
        }
        public void CanCompareDomainOffsetDifferences()
        {
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              _lv95_xyres_001_zres_001,
                              _lv95_xyres_001_zres_001_offsetdomains,
                              false, false, false,          // xy, z, m precisions
                              true, true));                 // tolerances, vcs

            Assert.IsFalse(SpatialReferenceUtils.AreEqual(
                               _lv95_xyres_001_zres_001,
                               _lv95_xyres_001_zres_001_offsetdomains,
                               true, false, false,           // xy, z, m precisions
                               true, true));                 // tolerances, vcs

            // NOTE: the z domain has an offset smaller than the z resolution, but IsZPrecisionEqual still returns true!!
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              _lv95_xyres_001_zres_001,
                              _lv95_xyres_001_zres_001_offsetdomains,
                              false, true, false,           // xy, z, m precisions
                              true, true));                 // tolerances, vcs
        }
        private static void AssertSameFeature(IFeature feature, IFeature rehydrated)
        {
            Assert.AreEqual(feature.OID, rehydrated.OID);
            Assert.AreEqual(feature.FeatureType, rehydrated.FeatureType);

            Assert.AreEqual(GdbObjectUtils.GetSubtypeCode(feature),
                            GdbObjectUtils.GetSubtypeCode(rehydrated));

            Assert.AreEqual(feature.Fields.FieldCount, rehydrated.Fields.FieldCount);
            Assert.AreEqual(feature.Class.ObjectClassID, rehydrated.Class.ObjectClassID);

            Assert.IsTrue(GeometryUtils.AreEqual(feature.Shape, rehydrated.Shape));
            Assert.IsTrue(GeometryUtils.AreEqual(feature.Extent, rehydrated.Extent));

            if (feature.Shape != null)
            {
                Assert.IsTrue(SpatialReferenceUtils.AreEqual(feature.Shape.SpatialReference,
                                                             rehydrated.Shape.SpatialReference,
                                                             true,
                                                             true));
            }
        }
예제 #19
0
        private static ISpatialReference GetUniqueSpatialReference(
            [NotNull] IEnumerable <IFeatureClass> featureClasses, out double tolerance)
        {
            Assert.ArgumentNotNull(featureClasses, nameof(featureClasses));

            ISpatialReference result = null;

            tolerance = 0;

            foreach (IFeatureClass featureClass in featureClasses)
            {
                var geoDataset = (IGeoDataset)featureClass;
                ISpatialReference spatialReference = geoDataset.SpatialReference;
                Assert.NotNull(spatialReference, "Dataset without spatial reference");

                if (result == null)
                {
                    result    = spatialReference;
                    tolerance = ((ISpatialReferenceTolerance)result).XYTolerance;
                }
                else
                {
                    const bool comparePrecisionAndTolerance     = true;
                    const bool compareVerticalCoordinateSystems = false;
                    if (!SpatialReferenceUtils.AreEqual(result, spatialReference,
                                                        comparePrecisionAndTolerance,
                                                        compareVerticalCoordinateSystems))
                    {
                        throw new ArgumentException(
                                  "All datasets must have the same spatial reference (with equal tolerance/resolution)");
                    }
                }
            }

            return(Assert.NotNull(
                       result, "No feature classes with spatial reference specified"));
        }
        private static void AssertDifferences([NotNull] ISpatialReference sref1,
                                              [NotNull] ISpatialReference sref2,
                                              bool equal, bool projectionEqual,
                                              bool vcsEqual,
                                              bool xyPrecisionEqual, bool zPrecisionEqual,
                                              bool mPrecisionEqual,
                                              bool xyToleranceEqual, bool zToleranceEqual,
                                              bool mToleranceEqual)
        {
            bool projectionDifferent;
            bool vcsDifferent;
            bool xyPrecisionDifferent;
            bool zPrecisionDifferent;
            bool mPrecisionDifferent;
            bool xyToleranceDifferent;
            bool zToleranceDifferent;
            bool mToleranceDifferent;
            bool isEqual = SpatialReferenceUtils.AreEqual(sref1, sref2,
                                                          out projectionDifferent,
                                                          out vcsDifferent,
                                                          out xyPrecisionDifferent,
                                                          out zPrecisionDifferent,
                                                          out mPrecisionDifferent,
                                                          out xyToleranceDifferent,
                                                          out zToleranceDifferent,
                                                          out mToleranceDifferent);

            Assert.AreEqual(equal, isEqual);
            Assert.AreEqual(projectionEqual, !projectionDifferent);
            Assert.AreEqual(vcsEqual, !vcsDifferent);
            Assert.AreEqual(xyPrecisionEqual, !xyPrecisionDifferent);
            Assert.AreEqual(zPrecisionEqual, !zPrecisionDifferent);
            Assert.AreEqual(mPrecisionEqual, !mPrecisionDifferent);
            Assert.AreEqual(xyToleranceEqual, !xyToleranceDifferent);
            Assert.AreEqual(zToleranceEqual, !zToleranceDifferent);
            Assert.AreEqual(mToleranceEqual, !mToleranceDifferent);
        }
예제 #21
0
        public void CanGetInteriorInteriorPolygon()
        {
            const string matrixString = "T********";

            IPolygon g1 = GeometryFactory.CreatePolygon(0, 0, 10, 10, 100);
            IPolygon g2 = GeometryFactory.CreatePolygon(5, 0, 15, 15, 1000);

            g1.SpatialReference = _spatialReference;
            g2.SpatialReference = _spatialReference;

            var matrix = new IntersectionMatrix(matrixString);

            IList <IGeometry> intersections = matrix.GetIntersections(g1, g2);

            WriteGeometries(intersections);

            Assert.AreEqual(1, intersections.Count);

            var polygon = (IPolygon)intersections[0];

            Assert.AreEqual(1, GeometryUtils.GetPartCount(polygon));
            Assert.IsTrue(SpatialReferenceUtils.AreEqual(_spatialReference,
                                                         polygon.SpatialReference));
        }
        public void CanCheckAreEqualWithPrecisionCompareFastEnough()
        {
            const bool comparePrecision = true;
            const bool compareVCS       = false;

            var watch = new Stopwatch();

            watch.Start();

            const int iterations = 1000;

            for (int i = 0; i < iterations; i++)
            {
                SpatialReferenceUtils.AreEqual(_lv95_xytol_01_ztol_01,
                                               _lv95lhn95_xytol_01_ztol_02,
                                               comparePrecision, compareVCS);
            }

            double perIteration = ((double)watch.ElapsedMilliseconds) / iterations;

            Console.WriteLine(@"AreEqual (precision compare): {0:N6} ms", perIteration);

            Assert.Less(perIteration, 0.05, "AreEqual takes too long");
        }
예제 #23
0
        public void CanCreateGdbRowFromRealData()
        {
            IWorkspace ws = TestUtils.OpenUserWorkspaceOracle();

            const string tlmStrasse = "TOPGIS_TLM.TLM_STRASSE";

            IFeatureClass realFeatureClass = DatasetUtils.OpenFeatureClass(ws, tlmStrasse);

            var objectClassMsg = ProtobufGdbUtils.ToObjectClassMsg(realFeatureClass, true);

            GdbTableContainer gdbTableContainer =
                ProtobufConversionUtils.CreateGdbTableContainer(
                    new[] { objectClassMsg }, null, out GdbWorkspace _);

            var virtualFeatureClass = (IFeatureClass)gdbTableContainer.OpenTable(tlmStrasse);

            Assert.AreEqual(realFeatureClass.ObjectClassID, virtualFeatureClass.ObjectClassID);
            Assert.AreEqual(DatasetUtils.GetName(realFeatureClass),
                            DatasetUtils.GetName(virtualFeatureClass));
            Assert.AreEqual(realFeatureClass.AliasName, virtualFeatureClass.AliasName);
            Assert.AreEqual(realFeatureClass.ShapeFieldName, virtualFeatureClass.ShapeFieldName);
            Assert.AreEqual(realFeatureClass.OIDFieldName, virtualFeatureClass.OIDFieldName);
            Assert.AreEqual(realFeatureClass.FeatureClassID, virtualFeatureClass.FeatureClassID);
            Assert.AreEqual(realFeatureClass.FeatureType, virtualFeatureClass.FeatureType);
            Assert.AreEqual(realFeatureClass.HasOID, virtualFeatureClass.HasOID);
            Assert.AreEqual(realFeatureClass.ShapeType, virtualFeatureClass.ShapeType);
            Assert.AreEqual(realFeatureClass.ShapeFieldName, virtualFeatureClass.ShapeFieldName);

            Assert.IsTrue(SpatialReferenceUtils.AreEqual(
                              DatasetUtils.GetSpatialReference(realFeatureClass),
                              DatasetUtils.GetSpatialReference(virtualFeatureClass), true, true));

            Assert.AreEqual(realFeatureClass.Fields.FieldCount,
                            virtualFeatureClass.Fields.FieldCount);

            int featureCount = 0;

            foreach (var feature in GdbQueryUtils.GetFeatures(realFeatureClass, true))
            {
                // TODO: Move all this to separate project referenced by both client and server
                GdbObjectMsg gdbObjectMsg =
                    ProtobufGdbUtils.ToGdbObjectMsg(feature, false, true);

                GdbRow gdbRow =
                    ProtobufConversionUtils.FromGdbObjectMsg(
                        gdbObjectMsg, (ITable)realFeatureClass);

                for (int i = 0; i < feature.Fields.FieldCount; i++)
                {
                    object expected = feature.get_Value(i);
                    object actual   = gdbRow.get_Value(i);

                    if (expected is IGeometry shape)
                    {
                        Assert.IsTrue(
                            GeometryUtils.AreEqual(shape, (IGeometry)actual));
                    }
                    else
                    {
                        Assert.AreEqual(expected, actual);
                    }
                }

                featureCount++;

                if (featureCount > 250)
                {
                    return;
                }
            }
        }
        public override int Execute()
        {
            ISpatialReference actualSpatialReference = GetSpatialReference(_featureClass);

            //const bool comparePrecisionAndTolerance = true;
            //const bool compareVerticalCoordinateSystems = true;

            bool coordinateSystemDifferent;
            bool vcsDifferent;
            bool xyPrecisionDifferent;
            bool zPrecisionDifferent;
            bool mPrecisionDifferent;
            bool xyToleranceDifferent;
            bool zToleranceDifferent;
            bool mToleranceDifferent;
            bool equal = SpatialReferenceUtils.AreEqual(_expectedSpatialReference,
                                                        actualSpatialReference,
                                                        out coordinateSystemDifferent,
                                                        out vcsDifferent,
                                                        out xyPrecisionDifferent,
                                                        out zPrecisionDifferent,
                                                        out mPrecisionDifferent,
                                                        out xyToleranceDifferent,
                                                        out zToleranceDifferent,
                                                        out mToleranceDifferent);

            if (equal)
            {
                return(NoError);
            }

            int errorCount = 0;

            if (coordinateSystemDifferent)
            {
                errorCount += Report(
                    Codes[Code.CoordinateSystemDifferent_XY],
                    LocalizableStrings.QaSchemaSpatialReference_CoordinateSystemDifferent,
                    _expectedSpatialReference.Name, actualSpatialReference.Name);
            }

            if (_compareVerticalCoordinateSystems && vcsDifferent)
            {
                errorCount += Report(
                    Codes[Code.CoordinateSystemDifferent_Z],
                    LocalizableStrings.QaSchemaSpatialReference_VerticalCoordinateSystemDifferent,
                    GetVCSDisplayName(_expectedSpatialReference),
                    GetVCSDisplayName(actualSpatialReference));
            }

            if (_compareXyPrecision && xyPrecisionDifferent)
            {
                errorCount += Report(
                    Codes[Code.PrecisionDifferent_XY],
                    LocalizableStrings.QaSchemaSpatialReference_XYDomainOrPrecisionDifferent,
                    GetXyPrecisionString(_expectedSpatialReference),
                    GetXyPrecisionString(actualSpatialReference));
            }

            if (_compareZPrecision && zPrecisionDifferent)
            {
                errorCount += Report(
                    Codes[Code.PrecisionDifferent_Z],
                    LocalizableStrings.QaSchemaSpatialReference_ZDomainOrPrecisionDifferent,
                    GetZPrecisionString(_expectedSpatialReference),
                    GetZPrecisionString(actualSpatialReference));
            }

            if (_compareMPrecision && mPrecisionDifferent)
            {
                errorCount += Report(
                    Codes[Code.PrecisionDifferent_M],
                    LocalizableStrings.QaSchemaSpatialReference_MDomainOrPrecisionDifferent,
                    GetMPrecisionString(_expectedSpatialReference),
                    GetMPrecisionString(actualSpatialReference));
            }

            if (_compareXyTolerance && xyToleranceDifferent)
            {
                errorCount += Report(
                    Codes[Code.ToleranceDifferent_XY],
                    LocalizableStrings.QaSchemaSpatialReference_XYToleranceDifferent,
                    GetXYToleranceString(_expectedSpatialReference),
                    GetXYToleranceString(actualSpatialReference));
            }

            if (_compareZTolerance && zToleranceDifferent)
            {
                errorCount += Report(
                    Codes[Code.ToleranceDifferent_Z],
                    LocalizableStrings.QaSchemaSpatialReference_ZToleranceDifferent,
                    GetZToleranceString(_expectedSpatialReference),
                    GetZToleranceString(actualSpatialReference));
            }

            if (_compareMTolerance && mToleranceDifferent)
            {
                errorCount += Report(
                    Codes[Code.ToleranceDifferent_M],
                    LocalizableStrings.QaSchemaSpatialReference_MToleranceDifferent,
                    GetMToleranceString(_expectedSpatialReference),
                    GetMToleranceString(actualSpatialReference));
            }

            return(errorCount);
        }