/// <summary>
        /// Returns <c>true</c> if this <see cref="IntersectionMatrix" /> is
        ///  T*T***T** (for two points or two surfaces)
        ///  1*T***T** (for two curves).
        /// </summary>
        /// <param name="dimensionOfGeometryA">The dimension of the first <see cref="IGeometry"/>.</param>
        /// <param name="dimensionOfGeometryB">The dimension of the second <see cref="IGeometry"/>.</param>
        /// <returns>
        /// <c>true</c> if the two <see cref="IGeometry"/>
        /// s related by this <see cref="IntersectionMatrix" /> overlap. For this
        /// function to return <c>true</c>, the <see cref="IGeometry"/>s must
        /// be two points, two curves or two surfaces.
        /// </returns>
        public bool IsOverlaps(Dimension dimensionOfGeometryA, Dimension dimensionOfGeometryB)
        {
            if ((dimensionOfGeometryA == Dimension.Point && dimensionOfGeometryB == Dimension.Point) ||
                (dimensionOfGeometryA == Dimension.Surface && dimensionOfGeometryB == Dimension.Surface))
                return IsTrue(_matrix[(int)Location.Interior, (int)Location.Interior]) &&
                       IsTrue(_matrix[(int)Location.Interior, (int)Location.Exterior]) &&
                       IsTrue(_matrix[(int)Location.Exterior, (int)Location.Interior]);

            if (dimensionOfGeometryA == Dimension.Curve && dimensionOfGeometryB == Dimension.Curve)
                return _matrix[(int)Location.Interior, (int)Location.Interior] == Dimension.Curve &&
                       IsTrue(_matrix[(int)Location.Interior, (int)Location.Exterior]) &&
                       IsTrue(_matrix[(int)Location.Exterior, (int)Location.Interior]);

            return false;
        }
        /// <summary>
        /// Returns <c>true</c> if this <see cref="IntersectionMatrix" /> is
        /// FT*******, F**T***** or F***T****.
        /// </summary>
        /// <param name="dimensionOfGeometryA">The dimension of the first <see cref="IGeometry"/>.</param>
        /// <param name="dimensionOfGeometryB">The dimension of the second <see cref="IGeometry"/>.</param>
        /// <returns>
        /// <c>true</c> if the two <see cref="IGeometry"/>
        /// s related by this <see cref="IntersectionMatrix" /> touch; Returns false
        /// if both <see cref="IGeometry"/>s are points.
        /// </returns>
        public bool IsTouches(Dimension dimensionOfGeometryA, Dimension dimensionOfGeometryB)
        {
            if (dimensionOfGeometryA > dimensionOfGeometryB)
                //no need to get transpose because pattern matrix is symmetrical
                return IsTouches(dimensionOfGeometryB, dimensionOfGeometryA);

            if ((dimensionOfGeometryA == Dimension.Surface && dimensionOfGeometryB == Dimension.Surface) ||
                (dimensionOfGeometryA == Dimension.Curve && dimensionOfGeometryB == Dimension.Curve) ||
                (dimensionOfGeometryA == Dimension.Curve && dimensionOfGeometryB == Dimension.Surface) ||
                (dimensionOfGeometryA == Dimension.Point && dimensionOfGeometryB == Dimension.Surface) ||
                (dimensionOfGeometryA == Dimension.Point && dimensionOfGeometryB == Dimension.Curve))
                return _matrix[(int)Location.Interior, (int)Location.Interior] == Dimension.False &&
                        (IsTrue(_matrix[(int)Location.Interior, (int)Location.Boundary]) ||
                         IsTrue(_matrix[(int)Location.Boundary, (int)Location.Interior]) ||
                         IsTrue(_matrix[(int)Location.Boundary, (int)Location.Boundary]));

            return false;
        }
        /// <summary> 
        /// Tests whether the argument dimensions are equal and 
        /// this <c>IntersectionMatrix</c> matches
        /// the pattern <tt>T*F**FFF*</tt>.
        /// <para/>
        /// <b>Note:</b> This pattern differs from the one stated in 
        /// <i>Simple feature access - Part 1: Common architecture</i>.
        /// That document states the pattern as <tt>TFFFTFFFT</tt>.  This would
        /// specify that
        /// two identical <tt>POINT</tt>s are not equal, which is not desirable behaviour.
        /// The pattern used here has been corrected to compute equality in this situation.
        /// </summary>
        /// <param name="dimensionOfGeometryA">The dimension of the first <see cref="IGeometry"/>.</param>
        /// <param name="dimensionOfGeometryB">The dimension of the second <see cref="IGeometry"/>.</param>
        /// <returns>
        /// <c>true</c> if the two <see cref="IGeometry"/>s
        /// related by this <see cref="IntersectionMatrix" /> are equal; the
        /// <see cref="IGeometry"/>s must have the same dimension to be equal.
        /// </returns>
        public bool IsEquals(Dimension dimensionOfGeometryA, Dimension dimensionOfGeometryB)
        {
            if (dimensionOfGeometryA != dimensionOfGeometryB)
                return false;

            return IsTrue(_matrix[(int)Location.Interior, (int)Location.Interior]) &&
                   _matrix[(int)Location.Interior, (int)Location.Exterior] == Dimension.False &&
                   _matrix[(int)Location.Boundary, (int)Location.Exterior] == Dimension.False &&
                   _matrix[(int)Location.Exterior, (int)Location.Interior] == Dimension.False &&
                   _matrix[(int)Location.Exterior, (int)Location.Boundary] == Dimension.False;
        }
 /// <summary>
 /// If row >= 0 and column >= 0, changes the specified element to <c>minimumDimensionValue</c>
 /// if the element is less. Does nothing if row is smaller to 0 or column is smaller to 0.
 /// </summary>
 /// <param name="row"></param>
 /// <param name="column"></param>
 /// <param name="minimumDimensionValue"></param>
 public void SetAtLeastIfValid(Location row, Location column, Dimension minimumDimensionValue)
 {
     if (row >= Location.Interior && column >= Location.Interior)
         SetAtLeast(row, column, minimumDimensionValue);
 }
 /// <summary>  
 /// Changes the elements of this <see cref="IntersectionMatrix" /> to <c>dimensionValue</c>.
 /// </summary>
 /// <param name="dimensionValue">
 /// The dimension value to which to set this <see cref="IntersectionMatrix" />
 /// s elements. Possible values <c>True, False, Dontcare, 0, 1, 2}</c>.
 /// </param>         
 public void SetAll(Dimension dimensionValue)
 {
     for (int ai = 0; ai < 3; ai++)
         for (int bi = 0; bi < 3; bi++)
             _matrix[ai, bi] = dimensionValue;
 }
 /// <summary>
 /// Changes the specified element to <c>minimumDimensionValue</c> if the element is less.
 /// </summary>
 /// <param name="row">
 /// The row of this <see cref="IntersectionMatrix" />, 
 /// indicating the interior, boundary or exterior of the first <see cref="IGeometry"/>.
 /// </param>
 /// <param name="column">
 /// The column of this <see cref="IntersectionMatrix" />, 
 /// indicating the interior, boundary or exterior of the second <see cref="IGeometry"/>.
 /// </param>
 /// <param name="minimumDimensionValue">
 /// The dimension value with which to compare the
 /// element. The order of dimension values from least to greatest is
 /// <c>True, False, Dontcare, 0, 1, 2</c>.
 /// </param>
 public void SetAtLeast(Location row, Location column, Dimension minimumDimensionValue)
 {
     if (_matrix[(int)row, (int)column] < minimumDimensionValue)
         _matrix[(int)row, (int)column] = minimumDimensionValue;
 }
 /// <summary>
 /// Changes the value of one of this <see cref="IntersectionMatrix" /> elements.
 /// </summary>
 /// <param name="row">
 /// The row of this <see cref="IntersectionMatrix" />,
 /// indicating the interior, boundary or exterior of the first <see cref="IGeometry"/>
 /// </param>
 /// <param name="column">
 /// The column of this <see cref="IntersectionMatrix" />,
 /// indicating the interior, boundary or exterior of the second <see cref="IGeometry"/>
 /// </param>
 /// <param name="dimensionValue">The new value of the element</param>        
 public void Set(Location row, Location column, Dimension dimensionValue)
 {
     _matrix[(int)row, (int)column] = dimensionValue;
 }
 /// <summary>  
 /// Tests if the dimension value satisfies the dimension symbol.
 /// </summary>
 /// <param name="actualDimensionValue">
 /// a number that can be stored in the <c>IntersectionMatrix</c>.
 /// Possible values are <c>{True, False, Dontcare, 0, 1, 2}</c>.
 /// </param>
 /// <param name="requiredDimensionSymbol">
 /// A character used in the string
 /// representation of an <see cref="IntersectionMatrix" />. 
 /// Possible values are <c>T, F, * , 0, 1, 2</c>.
 /// </param>
 /// <returns>
 /// <c>true</c> if the dimension symbol encompasses the dimension value.        
 /// </returns>        
 public static bool Matches(Dimension actualDimensionValue, char requiredDimensionSymbol)
 {
     if (requiredDimensionSymbol == DimensionUtility.SymDontcare)
         return true;
     if (requiredDimensionSymbol == DimensionUtility.SymTrue && (actualDimensionValue >= Dimension.Point || actualDimensionValue == Dimension.True))
         return true;
     if (requiredDimensionSymbol == DimensionUtility.SymFalse && actualDimensionValue == Dimension.False)
         return true;
     if (requiredDimensionSymbol == DimensionUtility.SymP && actualDimensionValue == Dimension.Point)
         return true;
     if (requiredDimensionSymbol == DimensionUtility.SymL && actualDimensionValue == Dimension.Curve)
         return true;
     if (requiredDimensionSymbol == DimensionUtility.SymA && actualDimensionValue == Dimension.Surface)
         return true;
     return false;
 }
 /// <summary>
 /// Tests if the dimension value matches <tt>TRUE</tt>
 /// (i.e.  has value 0, 1, 2 or TRUE).
 /// </summary>
 /// <param name="actualDimensionValue">A number that can be stored in the <c>IntersectionMatrix</c>.
 /// Possible values are <c>{<see cref="Dimension.True"/>, <see cref="Dimension.False"/>, <see cref="Dimension.Dontcare"/>, <see cref="Dimension.Point"/>, <see cref="Dimension.Curve"/>, <see cref="Dimension.Surface"/>}</c></param>
 /// <returns><c>true</c> if the dimension value matches <see cref="Dimension.True"/></returns>
 public static bool IsTrue(Dimension actualDimensionValue)
 {
     if (actualDimensionValue >= 0 || actualDimensionValue == Dimension.True)
     {
         return true;
     }
     return false;
 }
 /// <summary>
 /// Converts the dimension value to a dimension symbol,
 /// for example, <c>True => 'T'</c>
 /// </summary>
 /// <param name="dimensionValue">Number that can be stored in the <c>IntersectionMatrix</c>.
 /// Possible values are <c>True, False, Dontcare, 0, 1, 2</c>.</param>
 /// <returns>Character for use in the string representation of an <c>IntersectionMatrix</c>.
 /// Possible values are <c>T, F, * , 0, 1, 2</c>.</returns>
 public static char ToDimensionSymbol(Dimension dimensionValue)
 {
     switch (dimensionValue)
     {
         case Dimension.False:
             return SymFalse;
         case Dimension.True:
             return SymTrue;
         case Dimension.Dontcare:
             return SymDontcare;
         case Dimension.Point:
             return SymP;
         case Dimension.Curve:
             return SymL;
         case Dimension.Surface:
             return SymA;
         default:
             throw new ArgumentOutOfRangeException
                 ("Unknown dimension value: " + dimensionValue);
     }
 }