private void AssertResultStatisticsForLeafImplementation(
     CrsTransformationResult transformResult
 ) {
     CrsTransformationResultStatistic crsTransformationResultStatistic = transformResult.CrsTransformationResultStatistic;
     Assert.IsNotNull(crsTransformationResultStatistic);
     Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);
     Assert.AreEqual(1, crsTransformationResultStatistic.NumberOfPotentiallySuccesfulResults);
     Assert.AreEqual(0, crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude);
     Assert.AreEqual(0, crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude);
     Assert.AreEqual(transformResult.OutputCoordinate, crsTransformationResultStatistic.CoordinateAverage);
     Assert.AreEqual(transformResult.OutputCoordinate, crsTransformationResultStatistic.CoordinateMedian);
 }
Exemple #2
0
 private CrsTransformationResult CreateCrsTransformationResult(
     CrsCoordinate outputCoordinate,
     ICrsTransformationAdapter adapter,
     CrsCoordinate inputCoordinateNotUsedInThisTest
 ) {
     Exception exceptionNull = null;
     bool isSuccessTrue = true;
     return CrsTransformationResult._CreateCrsTransformationResult(
         inputCoordinateNotUsedInThisTest,
         outputCoordinate,
         exceptionNull,
         isSuccessTrue,
         adapter,
         CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(new List<CrsTransformationResult>())
     );
 }
Exemple #3
0
 public void TransformResult_ShouldReturnStatisticsObjectWithCorrectAverageAndMeanAndMaxDiffValues_WhenCreatingResultWithListOfSubresults() {
     // Both the setup code and the verify/assertion code for this test method 
     // is placed in a base class because it is reused from another test class.
     // The keyword "super" is used below to make that more obvious.
     
     CrsTransformationResult transformResult = CrsTransformationResult._CreateCrsTransformationResult(
         base.inputCoordinateNotUsedInStatisticsTest,
         base.outputCoordinateNotUsedInStatisticsTest,
         null,
         true,
         base.compositeAdapterForResultTest,
         CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(base.listOfSubresultsForStatisticsTest)
     );
     CrsTransformationResultStatistic crsTransformationResultStatistic = transformResult.CrsTransformationResultStatistic;
     base.AssertCrsTransformationResultStatistic(crsTransformationResultStatistic);
 }
Exemple #4
0
 // Lots of method in this test class creates a 
 // CrsTransformationResult with three of the six 
 // parameters being exactly the same.
 // For that reason this helper method is used,
 // i.e. to not duplicate the three 
 // parameters almost always being the same.
 private CrsTransformationResult CreateCrsTransformationResult(
     //CrsCoordinate inputCoordinate: ,
     CrsCoordinate outputCoordinate,
     Exception exceptionOrNull,
     bool isSuccess
     //crsTransformationAdapterResultSource: ICrsTransformationAdapter,
     //nullableCrsTransformationResultStatistic: CrsTransformationResultStatistic// = null
 ) {
     var transformResult = CrsTransformationResult._CreateCrsTransformationResult(
         inputCoordinate,
         outputCoordinate,
         exceptionOrNull,
         isSuccess,
         base.compositeAdapterForResultTest,
         CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(base.listOfSubresultsForStatisticsTest)
     );
     return transformResult;
 }
        public void CalculateAggregatedResult_ShouldThrowException_WhenResultIsBasedOnLeafsNotBeingPartOfTheWeightedAverageAdapter()
        {
            CrsCoordinate coordinate = CrsCoordinateFactory.LatLon(59, 18);
            List <CrsTransformationResult> emptyListOfTransformationResults = new List <CrsTransformationResult>();

            ICrsTransformationAdapter             leafMightyLittleGeodesy = new CrsTransformationAdapterMightyLittleGeodesy();
            List <CrsTransformationAdapterWeight> leafWeightsForOnlyMightyLittleGeodesy = new List <CrsTransformationAdapterWeight> {
                weightFactory.CreateFromInstance(
                    leafMightyLittleGeodesy,
                    1
                    )
            };
            // The below type ICompositeStrategy is "internal" in the F# project but still available from here
            //  because of "InternalsVisibleTo" configuration in the .fsproj file.
            ICompositeStrategy compositeStrategyWeightedAverageForOnlyMightyLittleGeodesy = CompositeStrategyWeightedAverage._CreateCompositeStrategyWeightedAverage(leafWeightsForOnlyMightyLittleGeodesy);
            // The above composite was created with only one leaf in the list

            ICrsTransformationAdapter leafDotSpatial = new CrsTransformationAdapterDotSpatial();
            CrsTransformationResult   crsTransformationResultProblem = new CrsTransformationResult(
                coordinate,     // inputCoordinate irrelevant in this test so okay to use the same as the output
                coordinate,     // outputCoordinate
                null,           // exception
                true,           // isSuccess
                leafDotSpatial, // crsTransformationAdapterResultSource,
                CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(emptyListOfTransformationResults)
                );

            // The composite strategy used below was created with only MightyLittleGeodesy,
            // and therefore if the result (as below) would be based on "DotSpatial"
            // then there is a bug somewhere i.e. an exception is thrown
            // which is tested below
            InvalidOperationException exception = Assert.Throws <InvalidOperationException>(() => {
                compositeStrategyWeightedAverageForOnlyMightyLittleGeodesy._CalculateAggregatedResult(
                    new List <CrsTransformationResult> {
                    crsTransformationResultProblem
                },                            // allResults
                    coordinate,
                    coordinate.CrsIdentifier, //  crsIdentifier for OutputCoordinateSystem
                    leafDotSpatial            // SHOULD CAUSE EXCEPTION !
                    );
            },
                                                                                            "The result adapter was not part of the weighted average composite adapter"
                                                                                            );
        }
 public void TransformResultStatistic_ShouldCalculateCorrectAverageAndMeanAndMaxDiffValues() {
     // Both the setup code and the verify/assertion code for this test method 
     // is placed in a base class because it is reused from another test class
     // The keyword "base" is not needed but used below to make that more obvious.
     
     CrsTransformationResultStatistic crsTransformationResultStatistic = CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(
         base.listOfSubresultsForStatisticsTest
     );
     // the above factory method is "internal" in the F# project 
     // but still can be used from this test project 
     // because of the following configuration in the F# core project:
     //<ItemGroup>
     //  <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
     //    <_Parameter1>Programmerare.CrsTransformations.Test</_Parameter1>
     //  </AssemblyAttribute>
     //</ItemGroup>
     
     base.AssertCrsTransformationResultStatistic(crsTransformationResultStatistic);
 }
Exemple #7
0
        private void verifyThreeImplementations(
            CrsTransformationAdapterComposite crsTransformationAdapterComposite
            )
        {
            CrsCoordinate           input  = CrsCoordinateFactory.LatLon(59.0, 18.0);
            CrsTransformationResult result = crsTransformationAdapterComposite.Transform(input, EpsgNumber.SWEDEN__SWEREF99_TM__3006);

            Assert.IsNotNull(result);
            Assert.IsTrue(result.IsSuccess);
            const int numberOfImplementations = CrsTransformationAdapterTest.EXPECTED_NUMBER_OF_ADAPTER_LEAF_IMPLEMENTATIONS;

            Assert.AreEqual(numberOfImplementations, result.TransformationResultChildren.Count);
            CrsTransformationResultStatistic crsTransformationResultStatistic = result.CrsTransformationResultStatistic;

            Assert.IsNotNull(crsTransformationResultStatistic);
            Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);
            Assert.AreEqual(numberOfImplementations, crsTransformationResultStatistic.NumberOfPotentiallySuccesfulResults);
            Assert.That(crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude, Is.LessThan(0.001));
        }
Exemple #8
0
 protected void AssertCrsTransformationResultStatistic(CrsTransformationResultStatistic crsTransformationResultStatistic) {
     Assert.IsNotNull(crsTransformationResultStatistic);
     Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);
     Assert.AreEqual(
         listOfSubresultsForStatisticsTest.Count,
         crsTransformationResultStatistic.NumberOfPotentiallySuccesfulResults
     );
     Assert.AreEqual(
         this.expectedLatDiffMax, 
         crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude
     );
     Assert.AreEqual(
         this.expectedLonDiffMax, 
         crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude
     );
     CrsCoordinate coordinateAverage = crsTransformationResultStatistic.CoordinateAverage;
     CrsCoordinate coordinateMean = crsTransformationResultStatistic.CoordinateMedian;
     Assert.IsNotNull(coordinateAverage);
     Assert.IsNotNull(coordinateMean);
     Assert.AreEqual(this.expectedCoordinateMean, coordinateMean);
     Assert.AreEqual(this.expectedCoordinateAverage, coordinateAverage);
 }
        public void IsReliableTest()
        {
            var crsTransformationAdapterCompositeFactory = CrsTransformationAdapterCompositeFactory.Create();
            CrsTransformationAdapterComposite crsTransformationComposite = crsTransformationAdapterCompositeFactory.CreateCrsTransformationAverage();
            var children = crsTransformationComposite.TransformationAdapterChildren;

            Assert.AreEqual(3, children.Count);

            CrsCoordinate           wgs84coordinateInSweden            = CrsCoordinateFactory.LatLon(59.31, 18.04);
            CrsTransformationResult resultWhenTransformingToSwedishCRS = crsTransformationComposite.Transform(wgs84coordinateInSweden, EpsgNumber.SWEDEN__SWEREF99_TM__3006);

            Assert.IsNotNull(resultWhenTransformingToSwedishCRS);
            Assert.IsTrue(resultWhenTransformingToSwedishCRS.IsSuccess);
            CrsTransformationResultStatistic crsTransformationResultStatistic = resultWhenTransformingToSwedishCRS.CrsTransformationResultStatistic;

            Assert.IsNotNull(crsTransformationResultStatistic);
            Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);

            int actualNumberOfResults = crsTransformationResultStatistic.NumberOfPotentiallySuccesfulResults;

            Assert.AreEqual(
                EXPECTED_NUMBER_OF_ADAPTER_LEAF_IMPLEMENTATIONS,
                actualNumberOfResults
                );
            double actualMaxDiffXLongitude = crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude;
            double actualMaxDiffYLatitude  = crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude;
            double actualMaxDiffXorY       = Math.Max(actualMaxDiffXLongitude, actualMaxDiffYLatitude);

            Assert.That(actualMaxDiffXorY, Is.LessThan(0.01));

            Assert.IsTrue(resultWhenTransformingToSwedishCRS.IsReliable(actualNumberOfResults, actualMaxDiffXorY));

            // assertFalse below since trying to require one more result than available
            Assert.IsFalse(resultWhenTransformingToSwedishCRS.IsReliable(actualNumberOfResults + 1, actualMaxDiffXorY));

            // assertFalse below since trying to require too small maxdiff
            Assert.IsFalse(resultWhenTransformingToSwedishCRS.IsReliable(actualNumberOfResults, actualMaxDiffXorY - 0.00000000001));
        }
Exemple #10
0
        public void CSharpeExampleCode()
        {
            int epsgWgs84  = EpsgNumber.WORLD__WGS_84__4326;
            int epsgSweRef = EpsgNumber.SWEDEN__SWEREF99_TM__3006;

            Assert.AreEqual(4326, epsgWgs84);
            Assert.AreEqual(3006, epsgSweRef);

            CrsCoordinate centralStockholmWgs84 = CrsCoordinateFactory.LatLon(59.330231, 18.059196, epsgWgs84);

            ICrsTransformationAdapter crsTransformationAdapter     = CrsTransformationAdapterCompositeFactory.Create().CreateCrsTransformationMedian();
            CrsTransformationResult   centralStockholmResultSweRef = crsTransformationAdapter.Transform(centralStockholmWgs84, epsgSweRef);

            Assert.IsNotNull(centralStockholmResultSweRef);
            Assert.IsTrue(centralStockholmResultSweRef.IsSuccess);
            IList <CrsTransformationResult> transformationResultChildren = centralStockholmResultSweRef.TransformationResultChildren;

            // Reason for the below assertion with value 3 :
            // If the NuGet configuration includes all (currently three) adapter implementations, then the
            // above created 'Composite' implementation will below use all three 'leaf' implementations
            // and return a coordinate with a median longitude and a median latitude
            Assert.AreEqual(3, transformationResultChildren.Count);

            // Console.WriteLine(centralStockholmResultSweRef.OutputCoordinate);
            // Console output from the above code row:
            // CrsCoordinate(xEastingLongitude=674032.357177155, yNorthingLatitude=6580821.99121561, crsIdentifier=CrsIdentifier(crsCode='EPSG:3006', isEpsgCode=True, epsgNumber=3006))
            var outputCoordinate = centralStockholmResultSweRef.OutputCoordinate;

            Assert.IsNotNull(outputCoordinate);
            Assert.AreEqual(674032.357177155, outputCoordinate.XEastingLongitude, SmallDeltaValue);
            Assert.AreEqual(6580821.99121561, outputCoordinate.YNorthingLatitude, SmallDeltaValue);

            CrsTransformationResultStatistic crsTransformationResultStatistic = centralStockholmResultSweRef.CrsTransformationResultStatistic;
            var medianCoordinate = crsTransformationResultStatistic.CoordinateMedian;
            // the median values have already been tested above since we used 'CreateCrsTransformationMedian'
            // for creating the main result.
            var averageCoordinate = crsTransformationResultStatistic.CoordinateAverage;

            Assert.AreEqual(674032.35716645606, averageCoordinate.XEastingLongitude, SmallDeltaValue);
            Assert.AreEqual(6580821.9921956062, averageCoordinate.YNorthingLatitude, SmallDeltaValue);

            Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);
            Assert.AreEqual(3, crsTransformationResultStatistic.NumberOfPotentiallySuccesfulResults);
            Assert.That(crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude, Is.LessThan(0.01));
            Assert.That(crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude, Is.LessThan(0.01));

            // "Reliable True" below since there should be three sucesful results
            // and the absolute value for the difference between longitudes and longitudes
            // should be less than 0.01
            Assert.IsTrue(
                centralStockholmResultSweRef.IsReliable(
                    3,   // minimumNumberOfSuccesfulResults
                    0.01 // maxDeltaValueForXLongitudeAndYLatitude
                    )
                );

            // "Reliable False" below because too extreme requirements of equal values for all the results
            // i.e. very small tolerance for differences
            Assert.IsFalse(
                centralStockholmResultSweRef.IsReliable(
                    3,                      // minimumNumberOfSuccesfulResults
                    0.000000000000000000001 // maxDeltaValueForXLongitudeAndYLatitude
                    )
                );

            // "Reliable False" below because can not require 4 succesful values
            // when there are only 3 implementations
            Assert.IsFalse(
                centralStockholmResultSweRef.IsReliable(
                    4,   // minimumNumberOfSuccesfulResults
                    0.01 // maxDeltaValueForXLongitudeAndYLatitude
                    )
                );

            ICrsTransformationAdapter    crsTransformationAdapterResultSource = centralStockholmResultSweRef.CrsTransformationAdapterResultSource;
            CrsTransformationAdapteeType adapteeType = crsTransformationAdapterResultSource.AdapteeType;

            Assert.AreEqual(CrsTransformationAdapteeType.COMPOSITE_MEDIAN, adapteeType);
            var dict = new Dictionary <CrsTransformationAdapteeType, bool>();

            foreach (CrsTransformationResult crsTransformationResultLeaf in transformationResultChildren)
            {
                Assert.IsTrue(crsTransformationResultLeaf.IsSuccess);
                dict.Add(crsTransformationResultLeaf.CrsTransformationAdapterResultSource.AdapteeType, true);

                // Leafs always only have one result and thus there are zero difference between max and min result.
                // Therefore the below assertion should succeed
                Assert.IsTrue(
                    crsTransformationResultLeaf.IsReliable(
                        1,                                // minimumNumberOfSuccesfulResults
                        0.0000000000000000000000000000001 // maxDeltaValueForXLongitudeAndYLatitude
                        )
                    );

                // Leafs always only have one result and thus the below tested method should return False
                Assert.IsFalse(
                    crsTransformationResultLeaf.IsReliable(
                        2,  // minimumNumberOfSuccesfulResults
                        0.1 // maxDeltaValueForXLongitudeAndYLatitude
                        )
                    );

                CrsTransformationResultStatistic leafResultStatistic = crsTransformationResultLeaf.CrsTransformationResultStatistic;
                Assert.IsTrue(leafResultStatistic.IsStatisticsAvailable);
                Assert.AreEqual(1, leafResultStatistic.NumberOfPotentiallySuccesfulResults);
                Assert.That(leafResultStatistic.MaxDifferenceForXEastingLongitude, Is.LessThan(0.01));
                Assert.That(leafResultStatistic.MaxDifferenceForYNorthingLatitude, Is.LessThan(0.01));
            }
            Assert.AreEqual(3, dict.Count);
            Assert.IsTrue(dict.ContainsKey(CrsTransformationAdapteeType.LEAF_MIGHTY_LITTLE_GEODESY_1_0_1));
            Assert.IsTrue(dict.ContainsKey(CrsTransformationAdapteeType.LEAF_DOT_SPATIAL_2_0_0_RC1));
            Assert.IsTrue(dict.ContainsKey(CrsTransformationAdapteeType.LEAF_PROJ_NET_4_GEO_API_1_4_1));
        }
        public void SetUp()
        {
            weightFactory = CrsTransformationAdapterWeightFactory.Create();

            crsTransformationAdapterCompositeFactory = CrsTransformationAdapterCompositeFactory.Create();
            double[] outputLatitudes =
            {
                59.1,
                59.2,
                59.3,
                59.4,
                59.6,
            };
            expectedMedianLatitude  = 59.3;
            expectedAverageLatitude = 59.32;

            double[] outputLongitudes =
            {
                18.2,
                18.3,
                18.4,
                18.8,
                18.9
            };
            expectedMedianLongitude  = 18.4;
            expectedAverageLongitude = 18.52;

            outputCoordinateWgs84ForImplementation_1 = CrsCoordinateFactory.CreateFromLatitudeLongitude(outputLatitudes[0], outputLongitudes[3]);
            outputCoordinateWgs84ForImplementation_2 = CrsCoordinateFactory.CreateFromLatitudeLongitude(outputLatitudes[2], outputLongitudes[1]);
            outputCoordinateWgs84ForImplementation_3 = CrsCoordinateFactory.CreateFromLatitudeLongitude(outputLatitudes[4], outputLongitudes[4]);
            outputCoordinateWgs84ForImplementation_4 = CrsCoordinateFactory.CreateFromLatitudeLongitude(outputLatitudes[1], outputLongitudes[0]);
            outputCoordinateWgs84ForImplementation_5 = CrsCoordinateFactory.CreateFromLatitudeLongitude(outputLatitudes[3], outputLongitudes[2]);
            outputCoordinates = new List <CrsCoordinate> {
                outputCoordinateWgs84ForImplementation_1,
                outputCoordinateWgs84ForImplementation_2,
                outputCoordinateWgs84ForImplementation_3,
                outputCoordinateWgs84ForImplementation_4,
                outputCoordinateWgs84ForImplementation_5
            };

            mock1 = new Mock <ICrsTransformationAdapter>();
            mock2 = new Mock <ICrsTransformationAdapter>();
            mock3 = new Mock <ICrsTransformationAdapter>();
            mock4 = new Mock <ICrsTransformationAdapter>();
            mock5 = new Mock <ICrsTransformationAdapter>();

            leafAdapterImplementation_1 = mock1.Object;
            leafAdapterImplementation_2 = mock2.Object;
            leafAdapterImplementation_3 = mock3.Object;
            leafAdapterImplementation_4 = mock4.Object;
            leafAdapterImplementation_5 = mock5.Object;

            inputCoordinateSweref99 = CrsCoordinateFactory.CreateFromYNorthingLatitudeAndXEastingLongitude(6580822.0, 674032.0, EpsgNumber.SWEDEN__SWEREF99_TM__3006);

            CrsTransformationResult leafResult1 = CrsTransformationResult._CreateCrsTransformationResult(
                inputCoordinateSweref99,
                outputCoordinateWgs84ForImplementation_1,
                null,
                true,
                leafAdapterImplementation_1,
                CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(new List <CrsTransformationResult>())
                );
            CrsTransformationResult leafResult2 = CrsTransformationResult._CreateCrsTransformationResult(
                inputCoordinateSweref99,
                outputCoordinateWgs84ForImplementation_2,
                null,
                true,
                leafAdapterImplementation_2,
                CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(new List <CrsTransformationResult>())
                );
            CrsTransformationResult leafResult3 = CrsTransformationResult._CreateCrsTransformationResult(
                inputCoordinateSweref99,
                outputCoordinateWgs84ForImplementation_3,
                null,
                true,
                leafAdapterImplementation_3,
                CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(new List <CrsTransformationResult>())
                );
            CrsTransformationResult leafResult4 = CrsTransformationResult._CreateCrsTransformationResult(
                inputCoordinateSweref99,
                outputCoordinateWgs84ForImplementation_4,
                null,
                true,
                leafAdapterImplementation_4,
                CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(new List <CrsTransformationResult>())
                );
            CrsTransformationResult leafResult5 = CrsTransformationResult._CreateCrsTransformationResult(
                inputCoordinateSweref99,
                outputCoordinateWgs84ForImplementation_5,
                null,
                true,
                leafAdapterImplementation_5,
                CrsTransformationResultStatistic._CreateCrsTransformationResultStatistic(new List <CrsTransformationResult>())
                );

            crsIdentifierWGS84 = CrsIdentifierFactory.CreateFromEpsgNumber(EpsgNumber.WORLD__WGS_84__4326);

            mock1.Setup(leaf => leaf.Transform(inputCoordinateSweref99, crsIdentifierWGS84)).Returns(leafResult1);
            mock2.Setup(leaf => leaf.Transform(inputCoordinateSweref99, crsIdentifierWGS84)).Returns(leafResult2);
            mock3.Setup(leaf => leaf.Transform(inputCoordinateSweref99, crsIdentifierWGS84)).Returns(leafResult3);
            mock4.Setup(leaf => leaf.Transform(inputCoordinateSweref99, crsIdentifierWGS84)).Returns(leafResult4);
            mock5.Setup(leaf => leaf.Transform(inputCoordinateSweref99, crsIdentifierWGS84)).Returns(leafResult5);

            //mock1.Setup(leaf => leaf.LongNameOfImplementation).Returns("1");
            //mock2.Setup(leaf => leaf.LongNameOfImplementation).Returns("2");
            //mock3.Setup(leaf => leaf.LongNameOfImplementation).Returns("3");
            //mock4.Setup(leaf => leaf.LongNameOfImplementation).Returns("4");
            //mock5.Setup(leaf => leaf.LongNameOfImplementation).Returns("5");
            mock1.Setup(leaf => leaf.AdapteeType).Returns(CrsTransformationAdapteeType.LEAF_DOT_SPATIAL_2_0_0_RC1);
            mock2.Setup(leaf => leaf.AdapteeType).Returns(CrsTransformationAdapteeType.LEAF_PROJ_NET_2_0_0);
            mock3.Setup(leaf => leaf.AdapteeType).Returns(CrsTransformationAdapteeType.LEAF_MIGHTY_LITTLE_GEODESY_1_0_2);
            // The type must be different but there are only three concrete types as above to use
            // but then instead can use the ones below (and the purpose of this enum is to use it as key in a dictionary/hashtable)
            mock4.Setup(leaf => leaf.AdapteeType).Returns(CrsTransformationAdapteeType.UNSPECIFIED_LEAF);
            mock5.Setup(leaf => leaf.AdapteeType).Returns(CrsTransformationAdapteeType.UNSPECIFIED);

            allLeafAdapters = new List <ICrsTransformationAdapter> {
                leafAdapterImplementation_1,
                leafAdapterImplementation_2,
                leafAdapterImplementation_3,
                leafAdapterImplementation_4,
                leafAdapterImplementation_5
            };
        }
    public void IsReliable_ShouldReturnTrueOrFalseForComposites_DependingOnCriteriasUsedAsMethodParameter() {
        // the below value is the max difference when comparing the three leaf implementations 
        double actualMaxDiffXorY = 0.0032574664801359177;
        // the above value is obviously fragile and might change if/when some adaptee library is upgraded
       
        int criteriaNumberOfResultsSuccess = EXPECTED_NUMBER_OF_ADAPTER_LEAF_IMPLEMENTATIONS; // all 3 should succeed
        int criteriaNumberOfResultsFailure = EXPECTED_NUMBER_OF_ADAPTER_LEAF_IMPLEMENTATIONS + 1; // 4 implementations can not currently succeed since there are currently not so many implementations
        double criteriaMaxDiffFailure = actualMaxDiffXorY - 0.0001; // a little too small requirement for max difference
        double criteriaMaxDiffSuccess  = actualMaxDiffXorY + 0.0001; // should result in success since the actual number is smaller 

        List<ICrsTransformationAdapter> crsTransformationAdapterImplementationsExpectingManyResults = new List<ICrsTransformationAdapter>();
        foreach (ICrsTransformationAdapter crsTransformationAdapterComposite in base.crsTransformationAdapterCompositeImplementations) {
            if(crsTransformationAdapterComposite.AdapteeType != CrsTransformationAdapteeType.COMPOSITE_FIRST_SUCCESS) {
                crsTransformationAdapterImplementationsExpectingManyResults.Add(crsTransformationAdapterComposite);
            }
        }
        Assert.AreEqual(
            3, // 3 composites i.e. all composite except COMPOSITE_FIRST_SUCCESS
            crsTransformationAdapterImplementationsExpectingManyResults.Count
        ); 
        
        foreach (ICrsTransformationAdapter crsTransformationAdapterComposite in crsTransformationAdapterImplementationsExpectingManyResults) {
            CrsCoordinate wgs84coordinateInSweden = CrsCoordinateFactory.LatLon(59.29,18.03);
            CrsTransformationResult resultWhenTransformingToSwedishCRS = crsTransformationAdapterComposite.Transform(wgs84coordinateInSweden, EpsgNumber.SWEDEN__SWEREF99_TM__3006);
            Assert.IsNotNull(resultWhenTransformingToSwedishCRS);
            Assert.IsTrue(resultWhenTransformingToSwedishCRS.IsSuccess);
            CrsTransformationResultStatistic crsTransformationResultStatistic = resultWhenTransformingToSwedishCRS.CrsTransformationResultStatistic;
            Assert.IsNotNull(crsTransformationResultStatistic);
            Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);
            // so far the same code as the previous test method for the test method with leafs
            
            int actualNumberOfResults = crsTransformationResultStatistic.NumberOfPotentiallySuccesfulResults;
            Assert.AreEqual(
				criteriaNumberOfResultsSuccess, 
				actualNumberOfResults
			);
            double actualMaxDiffXLongitude = crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude;
            double actualMaxDiffYLatitude = crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude;
            // double actualMaxDiffXorY = Math.max(actualMaxDiffXLongitude, actualMaxDiffYLatitude);
            // System.out.println("actualMaxDiffXorY " + actualMaxDiffXorY + "  " + crsTransformationAdapterComposite.getAdapteeType());

            // method "isReliable" used below is the method under test
            Assert.IsTrue(
                resultWhenTransformingToSwedishCRS.IsReliable(
                    criteriaNumberOfResultsSuccess,
                    criteriaMaxDiffSuccess
                )
            );
            Assert.IsFalse(
                resultWhenTransformingToSwedishCRS.IsReliable(
                    criteriaNumberOfResultsSuccess,
                    criteriaMaxDiffFailure
                )
            );
            Assert.IsFalse(
                resultWhenTransformingToSwedishCRS.IsReliable(
                    criteriaNumberOfResultsFailure,
                    criteriaMaxDiffSuccess
                )
            );
            Assert.IsFalse(
                resultWhenTransformingToSwedishCRS.IsReliable(
                    criteriaNumberOfResultsFailure,
                    criteriaMaxDiffFailure
                )
            );
        }
    }
    public void IsReliable_ShouldReturnTrueForLeafs_WhenUsingCriteriaNumberOfResultsOneAndMaxDiffZero() {
        int criteriaNumberOfResults = 1; // always one for a Leaf
        double criteriaMaxDiff = 0.0; // always zero for a Leaf
        // The tested method 'IsReliable' is actually relevant only for aggregated
        // transformations, but nevertheless there is a reaonable behavouor also
        // for the "Leaf" implementations regarding the number of results (always 1)
        // and the "differences" in lat/long for the "different" implementations
        // i.e. the "difference" should always be zero since there is only one implementation

        List<ICrsTransformationAdapter> crsTransformationAdapterImplementationsExpectingOneResult = new List<ICrsTransformationAdapter>();
        crsTransformationAdapterImplementationsExpectingOneResult.AddRange(base.crsTransformationAdapterLeafImplementations);
        crsTransformationAdapterImplementationsExpectingOneResult.Add(crsTransformationAdapterCompositeFactory.CreateCrsTransformationFirstSuccess());
        Assert.AreEqual(
			EXPECTED_NUMBER_OF_ADAPTER_LEAF_IMPLEMENTATIONS + 1,  // 3 leafs plus 1 
			crsTransformationAdapterImplementationsExpectingOneResult.Count
		);
        
        foreach (ICrsTransformationAdapter crsTransformationAdapterLeaf in crsTransformationAdapterImplementationsExpectingOneResult) {
            // suffix "Leaf" is not quite true, but in one of the iterations
            // it will be the Composite FirstSuccess which also will only have one result 
            // and thus can be tested in the same way as the leafs in this method
            CrsCoordinate wgs84coordinateInSweden = CrsCoordinateFactory.LatLon(59.29,18.03);
            CrsTransformationResult resultWhenTransformingToSwedishCRS = crsTransformationAdapterLeaf.Transform(wgs84coordinateInSweden, EpsgNumber.SWEDEN__SWEREF99_TM__3006);
            Assert.IsNotNull(resultWhenTransformingToSwedishCRS);
            Assert.IsTrue(resultWhenTransformingToSwedishCRS.IsSuccess);
            CrsTransformationResultStatistic crsTransformationResultStatistic = resultWhenTransformingToSwedishCRS.CrsTransformationResultStatistic;
            Assert.IsNotNull(crsTransformationResultStatistic);
            Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);
    
            int actualNumberOfResults = crsTransformationResultStatistic.NumberOfPotentiallySuccesfulResults;
            Assert.AreEqual(criteriaNumberOfResults, actualNumberOfResults);
            double actualMaxDiffXLongitude = crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude;
            double actualMaxDiffYLatitude = crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude;
            double actualMaxDiffXorY = Math.Max(actualMaxDiffXLongitude, actualMaxDiffYLatitude);
            Assert.AreEqual(criteriaMaxDiff, actualMaxDiffXorY); // zero differences since there should be only one result !

            // method "IsReliable" used below is the method under test
            
            Assert.IsTrue(
                resultWhenTransformingToSwedishCRS.IsReliable(
                    criteriaNumberOfResults, 
                    criteriaMaxDiff
                )
            );
    
            // Assert.IsFalse below since trying to require one more result than available
            Assert.IsFalse(
                resultWhenTransformingToSwedishCRS.IsReliable(
                    criteriaNumberOfResults + 1,
                    criteriaMaxDiff
                )
            );
    
            // Assert.IsFalse below since trying to require too small maxdiff
            Assert.IsFalse(
                resultWhenTransformingToSwedishCRS.IsReliable(
                    criteriaNumberOfResults, 
                    criteriaMaxDiff - 0.00000000001
                )
            );
        }
    }
Exemple #14
0
public void method() {
    Console.WriteLine("LargerCSharpeExample starts");

    // Some terminology regarding the names used in the below code example:
    // "CRS" = Coordinate Reference System
    // "WGS84" is the most frequently used coordinate system (e.g. the coordinates usually used in a GPS)    
    // "SWEREF99TM" is the official coordinate system used by authorities in Sweden
    // "EPSG" = "European Petroleum Survey Group" was (but the EPSG name is still often used) 
    //           an organization defining CRS with integer numbers e.g.  4326 for WGS84 or 3006 for SWEREF99TM
    int epsgWgs84  = EpsgNumber.WORLD__WGS_84__4326;
    int epsgSweRef = EpsgNumber.SWEDEN__SWEREF99_TM__3006;
    // The above "EpsgNumber" class with LOTS OF constants (and more constants classes) have been generated, 
    // using "FreeMarker" and database downloaded from EPSG ( http://www.epsg.org or http://www.epsg-registry.org ) 
    // from "crs-transformation-code-generation" in the project https://github.com/TomasJohansson/crsTransformations

    CrsCoordinate centralStockholmWgs84 = CrsCoordinateFactory.LatLon(59.330231, 18.059196, epsgWgs84);
    // https://kartor.eniro.se/m/03Yxp
    // SWEREF99TM coordinates (for WGS84 59.330231, 18.059196) 
    // according to Eniro (above URL): 6580822, 674032 (northing, easting)
    
    ICrsTransformationAdapter crsTransformationAdapter; // interface with concrete "leaf" implementation or "composite" implementations
    // This code example is using a "composite" which will use multiple libraries to do the same transformation and then 
    // return a coordinate with the median values (median of the northing values and median of the easting values)  
    crsTransformationAdapter = CrsTransformationAdapterCompositeFactory.Create().CreateCrsTransformationMedian();
    // The above factory will try to use those known objects which implements the interface i.e. the number 
    // of "leaf" objects will depend on how many you included as for example NuGet dependencies (three in the above NuGet example)
    Console.WriteLine("Number of 'leafs' : " + crsTransformationAdapter.TransformationAdapterChildren.Count);
    // Console output from the above row:
    // Number of 'leafs' : 3

    // Transform the WGS84 coordinate to a SWEREF99TM coordinate:
    CrsCoordinate centralStockholmSweRef = crsTransformationAdapter.TransformToCoordinate(centralStockholmWgs84, epsgSweRef);
    Console.WriteLine("Median Composite Northing: " + centralStockholmSweRef.Northing);
    Console.WriteLine("Median Composite Easting: " + centralStockholmSweRef.Easting);
    // Console output from the above two rows:
    //      Median Composite Northing: 6580821.99121561
    //      Median Composite Easting: 674032.357177155
    // (and these can be compared with the 'Eniro' values above i.e. '6580822, 674032 (northing, easting)' )
    
    // The coordinate class provides four properties with different names for the same east-west value and 
    // four properties for the same name each north-south value, as below:
    //      Four EQUIVALENT properties:  Easting  , X , Longitude , XEastingLongitude
    //      Four EQUIVALENT properties:  Northing , Y , Latitude  , YNorthingLatitude
    // Regarding the above alternative methods, depending on the desired semantic in your context, you may want to use:
    //      X/Y for a geocentric or cartesian system
    //      Longitude/Latitude for a geodetic or geographic system
    //      Easting/Northing for a cartographic or projected system
    //      xEastingLongitude/yNorthingLatitude for general code handling different types of system
    
    // If you want more details for the result you can use the following 'Transform' method: 
    //  (instead of the method 'TransformToCoordinate' used above)
    CrsTransformationResult centralStockholmResultSweRef = crsTransformationAdapter.Transform(centralStockholmWgs84, epsgSweRef);
    if(!centralStockholmResultSweRef.IsSuccess) {
        Console.WriteLine("No coordinate result");
    }
    else {
        if(centralStockholmResultSweRef.IsReliable(
            2,      // minimumNumberOfSuccesfulResults
            0.01    // maxDeltaValueForXLongitudeAndYLatitude
        )) {
            // at least 2 succesful results and the maximal difference in northing or easting is less than 0.01
            // (and if you want to know the exact difference you can find it in this code example further down the page)
            Console.WriteLine("Reliable result"); // according to your chosen parameters to the method 'isReliable'    
        }
        else {
            Console.WriteLine("Not reliable result");
        }
        Console.WriteLine(centralStockholmResultSweRef.OutputCoordinate);
        // Console output from the above code row:
        // CrsCoordinate(xEastingLongitude=674032.357177155, yNorthingLatitude=6580821.99121561, crsIdentifier=CrsIdentifier(crsCode='EPSG:3006', isEpsgCode=True, epsgNumber=3006))
        
        // When your code is in a context where you only have the result (but not the adapter object) 
        // (e.g. in a method receiving the result as a parameter)
        // you can get back the object which created the result as below:
        ICrsTransformationAdapter crsTransformationAdapterResultSource = centralStockholmResultSweRef.CrsTransformationAdapterResultSource;
        CrsTransformationAdapteeType adapteeType = crsTransformationAdapterResultSource.AdapteeType;
        Console.WriteLine("adapteeType: " + adapteeType); // console output: COMPOSITE_MEDIAN
        // The above code row returned an enum which is not really a true adaptee just like the 'composite' is not a true adapter.
        // However, when iterating (as below) the "leaf" results, 
        // it might be more interesting to keep track of from where the different values originated
        IList<CrsTransformationResult> transformationResultChildren = centralStockholmResultSweRef.TransformationResultChildren;
        foreach (CrsTransformationResult crsTransformationResultLeaf in transformationResultChildren) {
            if(!crsTransformationResultLeaf.IsSuccess) continue; // continue with the next 'leaf'
            
            ICrsTransformationAdapter resultAdapter = crsTransformationResultLeaf.CrsTransformationAdapterResultSource;
            Console.WriteLine(resultAdapter.AdapteeType);
            // The above code row will output rows like this: 
            // "LEAF_PROJ_NET_4_GEO_API_1_4_1" or "LEAF_MIGHTY_LITTLE_GEODESY_1_0_1" and so on
            if(!crsTransformationResultLeaf.IsReliable(
                    2,      // minimumNumberOfSuccesfulResults
                    1000    // maxDeltaValueForXLongitudeAndYLatitude
            )) {
                // The above constraint "at least 2 implementations" will always fail because now we are dealing with "leafs"
                // The above delta value constraint has very high tolerance but it does not matter since 
                // the constraint about the number of implementations will fail
                Console.WriteLine("Only 'composites' can have more than one result and this is a 'leaf' and thus does not have at least two results");
            }
            Console.WriteLine("Adapter long name: " + resultAdapter.LongNameOfImplementation); // full class name including package
            Console.WriteLine("Adapter short name: " + resultAdapter.ShortNameOfImplementation); // class name suffix i.e. the unique part
            // The above "long" names will be for example:
            //      Programmerare.CrsTransformations.Adapter.DotSpatial.CrsTransformationAdapterDotSpatial
            //      Programmerare.CrsTransformations.Adapter.MightyLittleGeodesy.CrsTransformationAdapterMightyLittleGeodesy
            // The above "short" names will be for example:
            //      DotSpatial
            //      MightyLittleGeodesy
            Console.WriteLine("adaptee: " + resultAdapter.AdapteeType);
            // The above row will output for example:
            //      LEAF_DOT_SPATIAL_2_0_0_RC1
            //      LEAF_MIGHTY_LITTLE_GEODESY_1_0_1
            // (note that the version number is included for the adaptees)
            Console.WriteLine("isComposite: " + resultAdapter.IsComposite); // "False" since we are iterating "leaf" results
            Console.WriteLine("Coordinate result for " + resultAdapter.AdapteeType + " : " + crsTransformationResultLeaf.OutputCoordinate);
            // The above row will output these rows when doing the iteration:
            //      Coordinate result for LEAF_DOT_SPATIAL_2_0_0_RC1 : CrsCoordinate(xEastingLongitude=674032.357322213, yNorthingLatitude=6580821.99121561, crsIdentifier=CrsIdentifier(crsCode='EPSG:3006', isEpsgCode=True, epsgNumber=3006))
            //      Coordinate result for LEAF_PROJ_NET_4_GEO_API_1_4_1 : CrsCoordinate(xEastingLongitude=674032.357177155, yNorthingLatitude=6580821.99437121, crsIdentifier=CrsIdentifier(crsCode='EPSG:3006', isEpsgCode=True, epsgNumber=3006))
            //      Coordinate result for LEAF_MIGHTY_LITTLE_GEODESY_1_0_1 : CrsCoordinate(xEastingLongitude=674032.357, yNorthingLatitude=6580821.991, crsIdentifier=CrsIdentifier(crsCode='EPSG:3006', isEpsgCode=True, epsgNumber=3006))
            // Note that the median value for "x" is 674032.357177155 for the above 
            // three values 674032.357 , 674032.357177155 , 674032.357322213 . 
            // That is the same value as was displayed before the iteration of the children/leafs for the median composite.
            // The same applies for the above "y" i.e. the median is 6580821.99121561
            // for the three y values 6580821.991 , 6580821.99121561 , 6580821.99437121
        }
        // The result object also provides convenience methods for the results (which you of course otherwise might calculate by iterating the above results)
        CrsTransformationResultStatistic crsTransformationResultStatistic = centralStockholmResultSweRef.CrsTransformationResultStatistic;
        // Note that the initially created composite was a "median composite" returning the median as the main value, 
        // but you can also create an average composite and regardless you can access both the median and the average with the aggregated statistics object:
        Console.WriteLine("average coordinate: " + crsTransformationResultStatistic.CoordinateAverage);
        Console.WriteLine("median coordinate: " + crsTransformationResultStatistic.CoordinateMedian);
        // Console output from the above two rows:
        // average coordinate: CrsCoordinate(xEastingLongitude=674032.357166456, yNorthingLatitude=6580821.99219561, crsIdentifier=CrsIdentifier(crsCode='EPSG:3006', isEpsgCode=True, epsgNumber=3006))
        // median coordinate: CrsCoordinate(xEastingLongitude=674032.357177155, yNorthingLatitude=6580821.99121561, crsIdentifier=CrsIdentifier(crsCode='EPSG:3006', isEpsgCode=True, epsgNumber=3006))

        Console.WriteLine("MaxDifferenceForXEastingLongitude: " + crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude);
        Console.WriteLine("MaxDifferenceForYNorthingLatitude: " + crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude);
        // Output from the above two rows:
        // MaxDifferenceForXEastingLongitude: 0.000322213280014694
        // MaxDifferenceForYNorthingLatitude: 0.00337121076881886
        // As you can see in the above iteration, the min and max x values are 674032.357 and 674032.357322213 (and the difference is 0.000322213).
        // Similarly the min and max y values are 6580821.991 and 6580821.99437121 (and the difference is 0.00337121).
        // The above two "MaxDifference" methods are used within the implementation of the convenience method 'isReliable' 
        // (also illustrated in this example further above)
    
    } // else statement ends

    Console.WriteLine("LargerCSharpeExample ends");
    Console.ReadLine();
} // method ends
Exemple #15
0
        public void FindPotentialBuggyImplementationsHelper(
            int minEpsgCrsCode,
            int maxEpsgCrsCode,
            double?optionalDelta = null
            )
        {
            int    numberIfEpsgCodesToConsiderInIteration = maxEpsgCrsCode - minEpsgCrsCode;
            bool   manyWillBeIterated = numberIfEpsgCodesToConsiderInIteration > 100;
            double deltaDiffToUse     = manyWillBeIterated ? deltaDiff : double.MinValue;

            if (optionalDelta.HasValue)
            {
                deltaDiffToUse = optionalDelta.Value;
            }

            var crsTransformationAdapterCompositeFactory = CrsTransformationAdapterCompositeFactory.Create();
            CrsTransformationAdapterComposite crsTransformationComposite = crsTransformationAdapterCompositeFactory.CreateCrsTransformationMedian();

            verifyThreeImplementations(crsTransformationComposite); // to make sure that the above factory really creates an object which will use three implementations

            IList <CrsTransformationResult> transformResultsWithLargeDifferences = new List <CrsTransformationResult>();

            CrsIdentifier wgs84 = CrsIdentifierFactory.CreateFromEpsgNumber(EpsgNumber.WORLD__WGS_84__4326);

            var stopWatch = new Stopwatch();

            stopWatch.Start();
            IList <EpsgCrsAndAreaCodeWithCoordinates> coordinatesFromGeneratedCsvFile = CoordinateTestDataGeneratedFromEpsgDatabaseTest.GetCoordinatesFromGeneratedCsvFile();
            int seconds = (int)stopWatch.Elapsed.TotalSeconds;

            WriteLine("Time for reading the content of the input file: " + seconds);
            stopWatch.Restart();
            int totalNumberOfSeconds;

            WriteLine("number of rows to iterate: " + coordinatesFromGeneratedCsvFile.Count);
            for (int i = 0; i < coordinatesFromGeneratedCsvFile.Count; i++)
            {
                if (manyWillBeIterated && (i % 100 == 0))
                {
                    //WriteLine("number of rows iterated so far: " + i);
                    totalNumberOfSeconds = (int)stopWatch.Elapsed.TotalSeconds;
                    //WriteLine("Number of seconds so far: " + totalNumberOfSeconds);
                    // if (i > 50) break;
                }
                EpsgCrsAndAreaCodeWithCoordinates epsgCrsAndAreaCodeWithCoordinates = coordinatesFromGeneratedCsvFile[i];
                if (
                    epsgCrsAndAreaCodeWithCoordinates.epsgCrsCode < minEpsgCrsCode
                    ||
                    epsgCrsAndAreaCodeWithCoordinates.epsgCrsCode > maxEpsgCrsCode
                    )
                {
                    continue;
                }
                if (!manyWillBeIterated)
                {
                    //Console.WriteLine("iterated epsgCrsCode: " + epsgCrsAndAreaCodeWithCoordinates.epsgCrsCode);
                }


                CrsCoordinate coordinateInputWgs84 = CrsCoordinateFactory.CreateFromYNorthingLatitudeAndXEastingLongitude(epsgCrsAndAreaCodeWithCoordinates.centroidY, epsgCrsAndAreaCodeWithCoordinates.centroidX, wgs84);

                CrsTransformationResult resultOutputFromWgs4 = crsTransformationComposite.Transform(coordinateInputWgs84, epsgCrsAndAreaCodeWithCoordinates.epsgCrsCode);
                if (!resultOutputFromWgs4.IsSuccess)
                {
                    continue;
                }

                CrsTransformationResult resultWhenTransformedBackToWgs84 = crsTransformationComposite.Transform(resultOutputFromWgs4.OutputCoordinate, wgs84);
                if (!resultWhenTransformedBackToWgs84.IsSuccess)
                {
                    continue;
                }

                CrsTransformationResultStatistic crsTransformationResultStatistic = resultWhenTransformedBackToWgs84.CrsTransformationResultStatistic;
                Assert.IsNotNull(crsTransformationResultStatistic);
                Assert.IsTrue(crsTransformationResultStatistic.IsStatisticsAvailable);
                if (
                    crsTransformationResultStatistic.MaxDifferenceForXEastingLongitude > deltaDiffToUse
                    ||
                    crsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude > deltaDiffToUse
                    )
                {
                    transformResultsWithLargeDifferences.Add(resultWhenTransformedBackToWgs84);
                }
                else
                {
                    if (!manyWillBeIterated)
                    {
                        //Console.WriteLine("NOT 'big' difference for EPSG " + epsgCrsAndAreaCodeWithCoordinates.epsgCrsCode);
                        int count = crsTransformationComposite.TransformationAdapterChildren.Count;
                        //Console.WriteLine("Number of implementations not having big difference: " + count);
                    }
                }
            }
            WriteLine("Number of iterated rows/coordinates: " + coordinatesFromGeneratedCsvFile.Count);

            WriteLine("Number of results with 'large' differences: " + transformResultsWithLargeDifferences.Count);
            for (int i = 0; i < transformResultsWithLargeDifferences.Count; i++)
            {
                CrsTransformationResult transformResult = transformResultsWithLargeDifferences[i];
                WriteLine("----------------------------------------");
                WriteLine("epsg " + transformResult.InputCoordinate.CrsIdentifier.CrsCode);
                WriteLine("MaxDiffYLatitude : " + transformResult.CrsTransformationResultStatistic.MaxDifferenceForYNorthingLatitude);
                WriteLine("MaxDiffYLongitude: " + transformResult.CrsTransformationResultStatistic.MaxDifferenceForXEastingLongitude);
                IList <CrsTransformationResult> subResults = transformResult.TransformationResultChildren;
                for (int j = 0; j < subResults.Count; j++)
                {
                    CrsTransformationResult subTransformResult = subResults[j];
                    if (subTransformResult.IsSuccess)
                    {
                        WriteLine(subTransformResult.OutputCoordinate + " , " + subTransformResult.CrsTransformationAdapterResultSource.AdapteeType);
                    }
                }
            }
        }