/// <summary>Initializes a new instance of the <see cref="HInterpolation"/> class.
            /// </summary>
            /// <param name="gridPointMatrix">The grid point matrix.</param>
            /// <param name="verticalCurveFactory">A factory for grid point curves along vertical direction, i.e. taken into account a specified interpolation, parametrization etc.</param>
            /// <param name="horizontalInterpolator">The interpolation approach along horizontal direction.</param>
            /// <param name="horizontalLeftExtrapolator">The extrapolation approach in horizontal direction on the left side of the grid points.</param>
            /// <param name="horizontalRightExtrapolator">The extrapolation approach in horizontal direction on the right side of the grid points.</param>
            internal HInterpolation(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPointMatrix, Func <THorizontalLabel, IGridPointCurveFactory <TVerticalLabel> > verticalCurveFactory, GridPointCurve.Interpolator horizontalInterpolator, GridPointCurve.Extrapolator horizontalLeftExtrapolator, GridPointCurve.Extrapolator horizontalRightExtrapolator)
                : base(gridPointMatrix, verticalCurveFactory)
            {
                m_HorizontalInterpolatorFactory = horizontalInterpolator ?? throw new NullReferenceException(nameof(horizontalInterpolator));
                m_HorizontalInterpolator        = horizontalInterpolator.Create();

                if (horizontalLeftExtrapolator == null)
                {
                    throw new NullReferenceException(nameof(horizontalLeftExtrapolator));
                }
                if (horizontalLeftExtrapolator.ExtrapolationBuildingDirection != GridPointCurve.Extrapolator.BuildingDirection.FromFirstGridPoint)
                {
                    throw new ArgumentException(String.Format("Invalid building direction of extrapolation on left side of the grid points."), nameof(horizontalLeftExtrapolator));
                }
                m_HorizontalLeftExtrapolatorFactory = horizontalLeftExtrapolator;
                m_HorizontalLeftExtrapolator        = horizontalLeftExtrapolator.Create(m_HorizontalInterpolator);

                if (horizontalRightExtrapolator == null)
                {
                    throw new NullReferenceException(nameof(horizontalRightExtrapolator));
                }
                if (horizontalRightExtrapolator.ExtrapolationBuildingDirection != GridPointCurve.Extrapolator.BuildingDirection.FromLastGridPoint)
                {
                    throw new ArgumentException(String.Format("Invalid building direction of extrapolation on the right side of the grid points."), nameof(horizontalRightExtrapolator));
                }
                m_HorizontalRightExtrapolatorFactory = horizontalRightExtrapolator;
                m_HorizontalRightExtrapolator        = horizontalRightExtrapolator.Create(m_HorizontalInterpolator);

                m_TempValuesForHorizontalEvaluation = new double[m_HorizontalDoubleLabels.Length];
                m_TempHorizontalDoubleLabels        = new double[m_GridPointMatrix.ColumnCount];
            }
        public void IndexerProperty_AtNoneReplenishedGridPoint_BenchmarkResult1(LabelMatrix.MissingValueReplenishment missingValueReplenishment, LabelMatrix.OrderOfInput orderOfInput)
        {
            /* some sample data, matrix is provided column-by-column: */
            var matrixEntries = new double[] { 1, 2, 3, 4, Double.NaN, 6, 7, 8, 9 };
            var xLabels       = new double[] { 1.1, 2.12, 3.4 };
            var yLabels       = new double[] { 1.05, 2.07, 3.65 };

            int rowCount    = 3;
            int columnCount = 3;
            var labelMatrix = LabelMatrix.Create(rowCount, columnCount, matrixEntries, xLabels, yLabels, missingValueReplenishment, orderOfInput);

            var indexCollection = new Tuple <int, int, int>[] {  // (rowIndex, columnIndex, Index of 'matrixEntries')
                Tuple.Create(0, 0, 0),
                Tuple.Create(1, 0, 1),
                Tuple.Create(2, 0, 2),
                Tuple.Create(0, 1, 3),
                // skip the 'NaN' value in this test
                Tuple.Create(2, 1, 5),
                Tuple.Create(0, 2, 6),
                Tuple.Create(1, 2, 7),
                Tuple.Create(2, 2, 8)
            };

            foreach (var indices in indexCollection)
            {
                int rowIndex    = indices.Item1;
                int columnIndex = indices.Item2;
                int expectedMatrixEntryIndex = indices.Item3;

                double actual   = labelMatrix[rowIndex, columnIndex];
                double expected = matrixEntries[expectedMatrixEntryIndex];

                Assert.That(actual, Is.EqualTo(expected).Within(1E-7), String.Format("Row: {0}, Column: {1}, expected: {2}, actual: {3}", rowIndex, columnIndex, expected, actual));
            }
        }
Beispiel #3
0
            /// <summary>Initializes a new instance of the <see cref="VInterpolation"/> class.
            /// </summary>
            /// <param name="gridPointMatrix">The grid point matrix.</param>
            /// <param name="horizontalCurveFactory">A factory for grid point curves along horizontal direction, i.e. taken into account a specified interpolation, parametrization etc.</param>
            /// <param name="verticalInterpolator">The interpolation approach along vertical direction.</param>
            /// <param name="verticalAboveExtrapolator">The extrapolation approach in vertical direction above the grid points.</param>
            /// <param name="verticalBelowExtrapolator">The extrapolation approach in vertical direction below the grid points.</param>
            internal VInterpolation(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPointMatrix, Func <TVerticalLabel, IGridPointCurveFactory <THorizontalLabel> > horizontalCurveFactory, GridPointCurve.Interpolator verticalInterpolator, GridPointCurve.Extrapolator verticalAboveExtrapolator, GridPointCurve.Extrapolator verticalBelowExtrapolator)
                : base(gridPointMatrix, horizontalCurveFactory)
            {
                m_VerticalInterpolatorFactory = verticalInterpolator ?? throw new NullReferenceException(nameof(verticalInterpolator));
                m_VerticalInterpolator        = verticalInterpolator.Create();

                if (verticalAboveExtrapolator == null)
                {
                    throw new NullReferenceException(nameof(verticalAboveExtrapolator));
                }
                if (verticalAboveExtrapolator.ExtrapolationBuildingDirection != GridPointCurve.Extrapolator.BuildingDirection.FromFirstGridPoint)
                {
                    throw new ArgumentException(String.Format("Invalid building direction of extrapolation above grid points."), nameof(verticalAboveExtrapolator));
                }
                m_VerticalAboveExtrapolatorFactory = verticalAboveExtrapolator;
                m_VerticalAboveExtrapolator        = verticalAboveExtrapolator.Create(m_VerticalInterpolator);

                if (verticalBelowExtrapolator == null)
                {
                    throw new NullReferenceException(nameof(verticalBelowExtrapolator));
                }
                if (verticalBelowExtrapolator.ExtrapolationBuildingDirection != GridPointCurve.Extrapolator.BuildingDirection.FromLastGridPoint)
                {
                    throw new ArgumentException(String.Format("Invalid building direction of extrapolation below grid points."), nameof(verticalBelowExtrapolator));
                }
                m_VerticalBelowExtrapolatorFactory = verticalBelowExtrapolator;
                m_VerticalBelowExtrapolator        = verticalBelowExtrapolator.Create(m_VerticalInterpolator);

                m_TempValuesForVerticalEvaluation = new double[m_VerticalDoubleLabels.Length];
                m_TempVerticalDoubleLabels        = new double[m_GridPointMatrix.RowCount];
            }
            /// <summary>Initializes a new instance of the <see cref="HParametrization"/> class.
            /// </summary>
            /// <param name="gridPointMatrix">The grid point matrix.</param>
            /// <param name="verticalCurveFactory">A factory for grid point curves along vertical direction, i.e. taken into account a specified interpolation, parametrization etc.</param>
            /// <param name="horizontalParametrization">The interpolation approach along horizontal direction.</param>
            internal HParametrization(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPointMatrix, Func <THorizontalLabel, IGridPointCurveFactory <TVerticalLabel> > verticalCurveFactory, GridPointCurve.Parametrization horizontalParametrization)
                : base(gridPointMatrix, verticalCurveFactory)
            {
                m_HorizontalParametrizationFactory = horizontalParametrization ?? throw new NullReferenceException(nameof(horizontalParametrization));
                m_HorizontalParametrization        = horizontalParametrization.Create();

                m_TempValuesForHorizontalEvaluation = new double[m_HorizontalDoubleLabels.Length];
                m_TempHorizontalDoubleLabels        = new double[m_GridPointMatrix.ColumnCount];
            }
        public void GetValue_TestCase1(GridPointCurve.Interpolator horizontalInterpolator, GridPointCurve.Extrapolator horizontalLeftExtrapolator, GridPointCurve.Extrapolator horizontalRightExtrapolator, GridPointCurve.Interpolator verticalInterpolator, GridPointCurve.Extrapolator verticalAboveExtrapolator, GridPointCurve.Extrapolator verticalBelowExtrapolator, GridPointSurface2d.ConstructionOrder constructionOrder, double x, double y, double expected)
        {
            int rowCount    = 3;
            int columnCount = 3;
            var xLabels     = new double[] { 1.1, 2.12, 3.4 };
            var yLabels     = new double[] { 1.05, 2.07, 3.65 };

            double[] matrixEntries = new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // matrix is provided column-by-column

            var labelMatrix = LabelMatrix.Create(rowCount, columnCount, matrixEntries, xLabels, yLabels);

            var surface = GridPointSurface2d.Create(labelMatrix, horizontalInterpolator, horizontalLeftExtrapolator, horizontalRightExtrapolator, verticalInterpolator, verticalAboveExtrapolator, verticalBelowExtrapolator, constructionOrder);

            double actual = surface.GetValue(x, y);

            Assert.That(actual, Is.EqualTo(expected).Within(1E-7), String.Format("expected: {0}, actual: {1}", expected, actual));
        }
Beispiel #6
0
        public void IndexerProperty_yLinear_BenchmarkResult3(
            [Values(LabelMatrix.OrderOfInput.AscendingOrder, LabelMatrix.OrderOfInput.Disordered, LabelMatrix.OrderOfInput.DisorderedHorizontalLabels, LabelMatrix.OrderOfInput.DisorderedVerticalLabels)]
            LabelMatrix.OrderOfInput orderOfInput)
        {
            var matrixEntries = new double[] { 1, 2, 3, 4, Double.NaN, 6, 7, 8, 9, 10 };
            var xLabels       = new double[] { 1, 2 };
            var yLabels       = new double[] { 1, 2, 3, 4, 5 };

            int rowCount    = 5;
            int columnCount = 2;

            var missingValueReplenishment = LabelMatrix.MissingValueReplenishment.WeightedNearestGridPoints.yAxis.Linear;

            var labelMatrix = LabelMatrix.Create(rowCount, columnCount, matrixEntries, xLabels, yLabels, missingValueReplenishment, orderOfInput);

            double actual   = labelMatrix[4, 0];
            double expected = 4.0; // in y-direction only one value is available

            Assert.That(actual, Is.EqualTo(expected).Within(1E-7), String.Format("Row: {0}, Column: {1}, expected: {2}, actual: {3}", 0, 4, expected, actual));
        }
        public void IndexerProperty_yLinear_BenchmarkResult1(
            [Values(LabelMatrix.OrderOfInput.AscendingOrder, LabelMatrix.OrderOfInput.Disordered, LabelMatrix.OrderOfInput.DisorderedHorizontalLabels, LabelMatrix.OrderOfInput.DisorderedVerticalLabels)]
            LabelMatrix.OrderOfInput orderOfInput)
        {
            var matrixEntries = new double[] { 1, 2, 3, 4, Double.NaN, 6, 7, 8, 9 };
            var xLabels       = new double[] { 1.1, 2.12, 3.4 };
            var yLabels       = new double[] { 1.05, 2.07, 3.65 };

            int rowCount    = 3;
            int columnCount = 3;

            var missingValueReplenishment = LabelMatrix.MissingValueReplenishment.WeightedNearestGridPoints.yAxis.Linear;

            var labelMatrix = LabelMatrix.Create(rowCount, columnCount, matrixEntries, xLabels, yLabels, missingValueReplenishment, orderOfInput);

            double actual   = labelMatrix[1, 1];
            double expected = (yLabels[1] - yLabels[0]) * (6.0 - 4.0) / (yLabels[2] - yLabels[0]) + 4.0;  // a linear interpolation

            Assert.That(actual, Is.EqualTo(expected).Within(1E-7), String.Format("Row: {0}, Column: {1}, expected: {2}, actual: {3}", 1, 1, expected, actual));
        }
        public void IndexerProperty_xLinear_BenchmarkResult2(
            [Values(LabelMatrix.OrderOfInput.AscendingOrder, LabelMatrix.OrderOfInput.Disordered, LabelMatrix.OrderOfInput.DisorderedHorizontalLabels, LabelMatrix.OrderOfInput.DisorderedVerticalLabels)]
            LabelMatrix.OrderOfInput orderOfInput)
        {
            /* some sample data, matrix is provided column-by-column: */
            var matrixEntries = new double[] { 1, 2, 3, 4, Double.NaN, 6, 7, 8, 9, 10 };
            var xLabels       = new double[] { 1, 2, 3, 4, 5 };
            var yLabels       = new double[] { 1, 2 };

            int rowCount    = 2;
            int columnCount = 5;

            var missingValueReplenishment = LabelMatrix.MissingValueReplenishment.WeightedNearestGridPoints.xAxis.Linear;

            var labelMatrix = LabelMatrix.Create(rowCount, columnCount, matrixEntries, xLabels, yLabels, missingValueReplenishment, orderOfInput);

            double actual   = labelMatrix[0, 2];
            double expected = (xLabels[1] - xLabels[0]) * (7.0 - 3.0) / (xLabels[2] - xLabels[0]) + 3.0;  // a linear interpolation

            Assert.That(actual, Is.EqualTo(expected).Within(1E-7), String.Format("Row: {0}, Column: {1}, expected: {2}, actual: {3}", 0, 2, expected, actual));
        }
Beispiel #9
0
        public void GetValue_AtGridPoint_GridPointValue_TestCase2(GridPointCurve.Interpolator horizontalInterpolator, GridPointCurve.Extrapolator horizontalLeftExtrapolator, GridPointCurve.Extrapolator horizontalRightExtrapolator, GridPointCurve.Interpolator verticalInterpolator, GridPointCurve.Extrapolator verticalAboveExtrapolator, GridPointCurve.Extrapolator verticalBelowExtrapolator, GridPointSurface2d.ConstructionOrder constructionOrder)
        {
            int rowCount    = 2;
            int columnCount = 5;

            var xLabels = new double[] { 1.05, 2.6, 3, 4, 5 };
            var yLabels = new double[] { 1.3, 2.8 };

            var matrixEntries = new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // matrix is provided column-by-column
            var labelMatrix   = LabelMatrix.Create(rowCount, columnCount, matrixEntries, xLabels, yLabels);

            var surface = GridPointSurface2d.Create(labelMatrix, horizontalInterpolator, horizontalLeftExtrapolator, horizontalRightExtrapolator, verticalInterpolator, verticalAboveExtrapolator, verticalBelowExtrapolator, constructionOrder);

            for (int j = 0; j < rowCount; j++)
            {
                for (int k = 0; k < columnCount; k++)
                {
                    double expected = labelMatrix[j, k];

                    double actual = surface.GetValue(x: labelMatrix.HorizontalDoubleLabels[k], y: labelMatrix.VerticalDoubleLabels[j]);
                    Assert.That(actual, Is.EqualTo(expected).Within(1E-7), String.Format("Row: {0}, Column: {1}, expected: {2}, actual: {3}", j, k, expected, actual));
                }
            }
        }
Beispiel #10
0
        /// <summary>Creates a specified two-dimensional surface.
        /// </summary>
        /// <typeparam name="THorizontalLabel">The type of the horizontal label.</typeparam>
        /// <typeparam name="TVerticalLabel">The type of the vertical label.</typeparam>
        /// <param name="gridPoints">The grid points in its <see cref="LabelMatrix&lt;THorizontalLabel,TVerticalLabel&gt;"/> representation.</param>
        /// <param name="horizontalInterpolator">The interpolation approach along horizontal direction.</param>
        /// <param name="horizontalLeftExtrapolator">The extrapolation approach in horizontal direction on the left.</param>
        /// <param name="horizontalRightExtrapolator">The extrapolation approach in horizontal direction on the right.</param>
        /// <param name="verticalInterpolator">The interpolation approach along vertical direction.</param>
        /// <param name="verticalAboveExtrapolator">The extrapolation approach in vertical direction above the grid points.</param>
        /// <param name="verticalBelowExtrapolator">The extrapolation approach in vertical direction below the grid points.</param>
        /// <param name="constructionOrder">A value indicating the order of the vertical and horizontal interpolation, extrapolation etc.</param>
        /// <returns>An object that repesents the two-dimensional surface with respect to the specified grid points and interpolation/extrapolation.</returns>
        public static IGridPointSurface2d <THorizontalLabel, TVerticalLabel> Create <THorizontalLabel, TVerticalLabel>(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPoints, GridPointCurve.Interpolator horizontalInterpolator, GridPointCurve.Extrapolator horizontalLeftExtrapolator, GridPointCurve.Extrapolator horizontalRightExtrapolator, GridPointCurve.Interpolator verticalInterpolator, GridPointCurve.Extrapolator verticalAboveExtrapolator, GridPointCurve.Extrapolator verticalBelowExtrapolator, ConstructionOrder constructionOrder = ConstructionOrder.HorizontalVertical)
            where THorizontalLabel : IComparable <THorizontalLabel>, IEquatable <THorizontalLabel>
            where TVerticalLabel : IComparable <TVerticalLabel>, IEquatable <TVerticalLabel>
        {
            if (gridPoints == null)
            {
                throw new ArgumentNullException(nameof(gridPoints));
            }
            if (horizontalInterpolator == null)
            {
                throw new ArgumentNullException(nameof(horizontalInterpolator));
            }
            if (horizontalLeftExtrapolator == null)
            {
                throw new ArgumentNullException(nameof(horizontalLeftExtrapolator));
            }
            if (horizontalRightExtrapolator == null)
            {
                throw new ArgumentNullException(nameof(horizontalRightExtrapolator));
            }
            switch (constructionOrder)
            {
            case ConstructionOrder.HorizontalVertical:
                var horizontalCurveFactory = GridPointCurve.Factory.Create <THorizontalLabel>(horizontalInterpolator, horizontalLeftExtrapolator, horizontalRightExtrapolator);
                return(new HorizontalVerticalWiseSurface2d <THorizontalLabel, TVerticalLabel> .VInterpolation(gridPoints, verticalLabel => horizontalCurveFactory, verticalInterpolator, verticalAboveExtrapolator, verticalBelowExtrapolator));

            case ConstructionOrder.VerticalHorizontal:
                var verticalCurveFactory = GridPointCurve.Factory.Create <TVerticalLabel>(verticalInterpolator, verticalAboveExtrapolator, verticalBelowExtrapolator);
                return(new VerticalHorizontalWiseSurface2d <THorizontalLabel, TVerticalLabel> .HInterpolation(gridPoints, horizontalLabel => verticalCurveFactory, horizontalInterpolator, horizontalLeftExtrapolator, horizontalRightExtrapolator));

            default:
                throw new NotImplementedException();
            }
        }
Beispiel #11
0
 /// <summary>Creates a specified two-dimensional surface, where the interpolation, parametrization etc. takes place first in vertical direction and then in horizontal direction.
 /// </summary>
 /// <typeparam name="THorizontalLabel">The type of the horizontal label.</typeparam>
 /// <typeparam name="TVerticalLabel">The type of the vertical label.</typeparam>
 /// <param name="gridPoints">The grid points in its <see cref="LabelMatrix&lt;THorizontalLabel,TVerticalLabel&gt;"/> representation.</param>
 /// <param name="verticalCurveFactory">A factory for horizontal grid point curves.</param>
 /// <param name="horizontalParametrization">The (curve) parametrization in horizontal direction.</param>
 /// <returns>An object that repesents the two-dimensional surface with respect to the specified grid points and interpolation/extrapolation.</returns>
 public static IGridPointSurface2d <THorizontalLabel, TVerticalLabel> Create <THorizontalLabel, TVerticalLabel>(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPoints, Func <THorizontalLabel, IGridPointCurveFactory <TVerticalLabel> > verticalCurveFactory, GridPointCurve.Parametrization horizontalParametrization)
     where THorizontalLabel : IComparable <THorizontalLabel>, IEquatable <THorizontalLabel>
     where TVerticalLabel : IComparable <TVerticalLabel>, IEquatable <TVerticalLabel>
 {
     if (gridPoints == null)
     {
         throw new ArgumentNullException(nameof(gridPoints));
     }
     if (verticalCurveFactory == null)
     {
         throw new ArgumentNullException(nameof(verticalCurveFactory));
     }
     return(new VerticalHorizontalWiseSurface2d <THorizontalLabel, TVerticalLabel> .HParametrization(gridPoints, verticalCurveFactory, horizontalParametrization));
 }
Beispiel #12
0
 /// <summary>Creates a specified two-dimensional surface, where the interpolation, parametrization etc. takes place first in horizontal direction and then in vertical direction.
 /// </summary>
 /// <typeparam name="THorizontalLabel">The type of the horizontal label.</typeparam>
 /// <typeparam name="TVerticalLabel">The type of the vertical label.</typeparam>
 /// <param name="gridPoints">The grid points in its <see cref="LabelMatrix&lt;THorizontalLabel,TVerticalLabel&gt;"/> representation.</param>
 /// <param name="horizontalCurveFactory">A factory for horizontal grid point curves.</param>
 /// <param name="verticalInterpolator">The interpolation approach along vertical direction.</param>
 /// <param name="verticalAboveExtrapolator">The extrapolation approach in vertical direction above the grid points.</param>
 /// <param name="verticalBelowExtrapolator">The extrapolation approach in vertical direction below the grid points.</param>
 /// <returns>An object that repesents the two-dimensional surface with respect to the specified grid points and interpolation/extrapolation.</returns>
 public static IGridPointSurface2d <THorizontalLabel, TVerticalLabel> Create <THorizontalLabel, TVerticalLabel>(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPoints, Func <TVerticalLabel, IGridPointCurveFactory <THorizontalLabel> > horizontalCurveFactory, GridPointCurve.Interpolator verticalInterpolator, GridPointCurve.Extrapolator verticalAboveExtrapolator, GridPointCurve.Extrapolator verticalBelowExtrapolator)
     where THorizontalLabel : IComparable <THorizontalLabel>, IEquatable <THorizontalLabel>
     where TVerticalLabel : IComparable <TVerticalLabel>, IEquatable <TVerticalLabel>
 {
     if (gridPoints == null)
     {
         throw new ArgumentNullException(nameof(gridPoints));
     }
     if (horizontalCurveFactory == null)
     {
         throw new ArgumentNullException(nameof(horizontalCurveFactory));
     }
     return(new HorizontalVerticalWiseSurface2d <THorizontalLabel, TVerticalLabel> .VInterpolation(gridPoints, horizontalCurveFactory, verticalInterpolator, verticalAboveExtrapolator, verticalBelowExtrapolator));
 }
Beispiel #13
0
        /// <summary>Creates a specified two-dimensional surface.
        /// </summary>
        /// <typeparam name="THorizontalLabel">The type of the horizontal label.</typeparam>
        /// <typeparam name="TVerticalLabel">The type of the vertical label.</typeparam>
        /// <param name="gridPoints">The grid points in its <see cref="LabelMatrix&lt;THorizontalLabel,TVerticalLabel&gt;"/> representation.</param>
        /// <param name="horizontalParametrization">The (curve) parametrization in horizontal direction.</param>
        /// <param name="verticalParametrization">The (curve) parametrization in vertical direction.</param>
        /// <param name="constructionOrder">A value indicating the order of the vertical and horizontal interpolation, extrapolation etc.</param>
        /// <returns>An object that repesents the two-dimensional surface with respect to the specified grid points and interpolation/extrapolation.</returns>
        public static IGridPointSurface2d <THorizontalLabel, TVerticalLabel> Create <THorizontalLabel, TVerticalLabel>(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPoints, GridPointCurve.Parametrization horizontalParametrization, GridPointCurve.Parametrization verticalParametrization, ConstructionOrder constructionOrder = ConstructionOrder.HorizontalVertical)
            where THorizontalLabel : IComparable <THorizontalLabel>, IEquatable <THorizontalLabel>
            where TVerticalLabel : IComparable <TVerticalLabel>, IEquatable <TVerticalLabel>
        {
            if (gridPoints == null)
            {
                throw new ArgumentNullException(nameof(gridPoints));
            }
            switch (constructionOrder)
            {
            case ConstructionOrder.HorizontalVertical:
                var horizontalCurveFactory = GridPointCurve.Factory.Create <THorizontalLabel>(horizontalParametrization);
                return(new HorizontalVerticalWiseSurface2d <THorizontalLabel, TVerticalLabel> .VParametrization(gridPoints, verticalLabel => horizontalCurveFactory, verticalParametrization));

            case ConstructionOrder.VerticalHorizontal:
                var verticalCurveFactory = GridPointCurve.Factory.Create <TVerticalLabel>(verticalParametrization);
                return(new VerticalHorizontalWiseSurface2d <THorizontalLabel, TVerticalLabel> .HParametrization(gridPoints, horizontalLabel => verticalCurveFactory, horizontalParametrization));

            default:
                throw new NotImplementedException();
            }
        }
        /// <summary>Initializes a new instance of the <see cref="HorizontalVerticalWiseSurface2d&lt;THorizontalLabel, TVerticalLabel&gt;"/> class.
        /// </summary>
        /// <param name="gridPointMatrix">The grid point matrix.</param>
        /// <param name="horizontalCurveFactory">A factory for grid point curves along horizontal direction for each vertical label, i.e. taken into account a specified interpolation, parametrization etc.</param>
        protected HorizontalVerticalWiseSurface2d(LabelMatrix <THorizontalLabel, TVerticalLabel> gridPointMatrix, Func <TVerticalLabel, IGridPointCurveFactory <THorizontalLabel> > horizontalCurveFactory)
        {
            m_GridPointMatrix = gridPointMatrix ?? throw new ArgumentNullException(nameof(gridPointMatrix));

            if (horizontalCurveFactory == null)
            {
                throw new ArgumentNullException(nameof(horizontalCurveFactory));
            }

            m_HorizontalExactFitToGridPoints = true;
            if (gridPointMatrix.IsCompletelyDefined == true)
            {
                /* all grid points are valid numbers, i.e. take into account all rows and columns: */
                m_VerticalDoubleLabels = gridPointMatrix.VerticalDoubleLabels.ToArray();

                m_CurvesAlongHorizontalDirection = new IGridPointCurve <THorizontalLabel> [gridPointMatrix.RowCount];
                for (int j = 0; j < gridPointMatrix.RowCount; j++)
                {
                    var curveFactory = horizontalCurveFactory(gridPointMatrix.VerticalLabels[j]);
                    var curve        = curveFactory.Create(gridPointMatrix.ColumnCount, gridPointMatrix.HorizontalLabels, gridPointMatrix.HorizontalDoubleLabels, gridPointMatrix.Data, gridPointValueStartIndex: j, gridPointValueIncrement: gridPointMatrix.RowCount);

                    m_CurvesAlongHorizontalDirection[j] = curve;
                    m_HorizontalExactFitToGridPoints   &= (curveFactory.FittingQuality == FittingQuality.Exact);
                }
            }
            else /* ignore rows that contains to many Not-a-Number entries: */
            {
                var verticalDoubleLabels = new List <double>();
                m_VerticalLabelMapping = new Dictionary <int, int>();
                var curvesAlongHorizontalDirection = new List <IGridPointCurve <THorizontalLabel> >();

                for (int j = 0; j < gridPointMatrix.RowCount; j++)
                {
                    var curveFactory = horizontalCurveFactory(gridPointMatrix.VerticalLabels[j]);
                    var curve        = curveFactory.Create();
                    foreach (var(HorizontalLabel, HorizontalDoubleLabel, Value) in gridPointMatrix.GetRowWithLabels(j))
                    {
                        if (Double.IsNaN(Value) == false)
                        {
                            curve.Add(HorizontalLabel, HorizontalDoubleLabel, Value);
                        }
                    }
                    int minimalRequiredNumberOfGridPoints = curveFactory.MinimalRequiredNumberOfGridPoints;

                    if (curve.GridPointCount >= minimalRequiredNumberOfGridPoints)
                    {
                        curve.Update();
                        if (curve.IsOperable == false)
                        {
                            throw new NotOperableException(String.Format("Horizontal curve, row index = {0} is not operable.", j));
                        }
                        curvesAlongHorizontalDirection.Add(curve);
                        verticalDoubleLabels.Add(gridPointMatrix.VerticalDoubleLabels[j]);
                        m_HorizontalExactFitToGridPoints &= (curveFactory.FittingQuality == FittingQuality.Exact);

                        m_VerticalLabelMapping.Add(j, curvesAlongHorizontalDirection.Count - 1);
                    }
                    // else: ignore the horizontal curve
                }
                m_VerticalDoubleLabels           = verticalDoubleLabels.ToArray();
                m_CurvesAlongHorizontalDirection = curvesAlongHorizontalDirection.ToArray();
            }

            if (m_CurvesAlongHorizontalDirection.Length < 2)
            {
                throw new ArgumentException(String.Format("Only {0} valid rows available.", m_CurvesAlongHorizontalDirection.Length), "gridPointMatrix");
            }
        }