public override HitResult GetHitResult(Ray ray)
        {
            var a = Vector3.Dot(VerticalVector, ray.Direction);

            if (Math.Abs(a) < float.Epsilon)
            {
                return new HitResult {
                           Hit = false
                }
            }
            ;

            var b   = Vector3.Dot(VerticalVector, ray.Origin) - VerticalVector.Length() * DistanceFromOrigin;
            var res = -b / a;

            if (res <= 0)
            {
                return new HitResult {
                           Hit = false
                }
            }
            ;
            var hitPoint  = ray.Origin + res * ray.Direction;
            var maybeNorm = Vector3.Normalize(VerticalVector);

            return(new HitResult
            {
                Hit = true,
                HitPoint = hitPoint,
                HitNorm = Vector3.Dot(maybeNorm, ray.Direction) < 0 ? maybeNorm : -maybeNorm
            });
        }
    }
}
示例#2
0
    /// <summary>
    /// Calculates eigenvectors (loads) and the corresponding eigenvalues (scores)
    /// by means of the NIPALS algorithm
    /// </summary>
    /// <param name="X">The matrix to which the decomposition is applied to. A row of the matrix is one spectrum (or a single measurement giving multiple resulting values). The different rows of the matrix represent
    /// measurements under different conditions.</param>
    /// <param name="numFactors">The number of factors to be calculated. If 0 is provided, factors are calculated until the provided accuracy is reached. </param>
    /// <param name="accuracy">The relative residual variance that should be reached.</param>
    /// <param name="factors">Resulting matrix of factors. You have to provide a extensible matrix of dimension(0,0) as the vertical score vectors are appended to the matrix.</param>
    /// <param name="loads">Resulting matrix consiting of horizontal load vectors (eigenspectra). You have to provide a extensible matrix of dimension(0,0) here.</param>
    /// <param name="residualVarianceVector">Residual variance. Element[0] is the original variance, element[1] the residual variance after the first factor subtracted and so on. You can provide null if you don't need this result.</param>
    public static void NIPALS_HO(
      IMatrix X,
      int numFactors,
      double accuracy,
      IRightExtensibleMatrix factors,
      IBottomExtensibleMatrix loads,
      IBottomExtensibleMatrix residualVarianceVector)
    {
            
      // first center the matrix
      //MatrixMath.ColumnsToZeroMean(X, null);

      double originalVariance = Math.Sqrt(MatrixMath.SumOfSquares(X));
      
      if(null!=residualVarianceVector)
        residualVarianceVector.AppendBottom(new MatrixMath.Scalar(originalVariance));

  
      IMatrix l = new HorizontalVector(X.Columns);
      IMatrix t_prev = null;
      IMatrix t = new VerticalVector(X.Rows);

      int maxFactors = numFactors<=0 ? X.Columns : Math.Min(numFactors,X.Columns);

      for(int nFactor=0; nFactor<maxFactors; nFactor++)
      {
        //l has to be a horizontal vector
        // 1. Guess the transposed Vector l_transp, use first row of X matrix if it is not empty, otherwise the first non-empty row
        int rowoffset=0;
        do  
        {
          Submatrix(X,l,rowoffset,0);     // l is now a horizontal vector
          rowoffset++;
        } while(IsZeroMatrix(l) && rowoffset<X.Rows);



        for(int iter=0;iter<500;iter++)
        {
      
          // 2. Calculate the new vector t for the factor values
          MultiplySecondTransposed(X,l,t); // t = X*l_t (t is  a vertical vector)

          // Compare this with the previous one 
          if(t_prev!=null && IsEqual(t_prev,t,1E-9))
            break;

          // 3. Calculate the new loads 
          MultiplyFirstTransposed(t,X,l); // l = t_tr*X  (gives a horizontal vector of load (= eigenvalue spectrum)
          
          // normalize the (one) row
          NormalizeRows(l); // normalize the eigenvector spectrum

          // 4. Goto step 2 or break after a number of iterations
          if(t_prev==null)
            t_prev = new VerticalVector(X.Rows);
          Copy(t,t_prev); // stores the content of t in t_prev

        }

        // Store factor and loads
        factors.AppendRight(t);
        loads.AppendBottom(l);

        // 5. Calculate the residual matrix X = X - t*l 
        SubtractProductFromSelf(t,l,X); // X is now the residual matrix

        // if the number of factors to calculate is not provided,
        // calculate the norm of the residual matrix and compare with the original
        // one
        if(numFactors<=0 || null!=residualVarianceVector)
        {
          double residualVariance = Math.Sqrt(MatrixMath.SumOfSquares(X));
          residualVarianceVector.AppendBottom(new MatrixMath.Scalar(residualVariance));

          if(residualVariance<=accuracy*originalVariance)
          {
            break;
          }
        }
      } // for all factors
    } // end NIPALS