/// <summary>Returns the determinant of m. </summary> protected float determinant(dmat3 m) { throw _invalidAccess; }
/// <summary> /// Returns a matrix that is the transpose of m. /// The input matrix m is not modified. /// </summary> protected dmat3 transpose(dmat3 m) { throw _invalidAccess; }
/// <inheritdoc /> public double RayIntersect(Ray ray) { dvec3 rayStart = ray.StartPosition; dvec3 rayDirection = ray.Direction; DebugUtil.AssertAllFinite(rayStart, nameof(rayStart)); DebugUtil.AssertAllFinite(rayDirection, nameof(rayDirection)); // Since we raytrace only using a cylindrical surface that is horizontal and at the origin, we // first shift and rotate the ray such that we get the right orientation: dvec3 start = CenterCurve.GetStartPosition(); dvec3 end = CenterCurve.GetEndPosition(); DebugUtil.AssertAllFinite(start, nameof(start)); DebugUtil.AssertAllFinite(end, nameof(end)); dvec3 tangent = CenterCurve.GetTangentAt(0.0).Normalized; dvec3 normal = CenterCurve.GetNormalAt(0.0).Normalized; dvec3 binormal = CenterCurve.GetBinormalAt(0.0).Normalized; DebugUtil.AssertAllFinite(tangent, nameof(tangent)); DebugUtil.AssertAllFinite(normal, nameof(normal)); DebugUtil.AssertAllFinite(binormal, nameof(binormal)); double length = dvec3.Distance(start, end); DebugUtil.AssertFinite(length, nameof(length)); // CenterCurve is guaranteed to be a LineSegment, since the base property CenterCurve is masked by this // class' CenterCurve property that only accepts a LineSegment, and similarly this class' constructor only // accepts a LineSegment. The following mathematics, which assumes that the central axis is a line segment, // is therefore valid. dmat3 rotationMatrix = new dmat3(normal, binormal, tangent / length).Transposed; dvec3 rescaledRay = rotationMatrix * (rayStart - start); dvec3 newDirection = rotationMatrix * rayDirection.Normalized; double x0 = rescaledRay.x; double y0 = rescaledRay.y; double z0 = rescaledRay.z; double a = newDirection.x; double b = newDirection.y; double c = newDirection.z; // Raytrace using a cylindrical surface equation x^2 + y^2. The parameters in the following line // represent the coefficients of the expanded cylindrical surface equation, after the substitution // x = x_0 + a t and y = y_0 + b t: QuarticFunction surfaceFunction = new QuarticFunction(x0 * x0 + y0 * y0, 2.0 * (x0 * a + y0 * b), a * a + b * b, 0.0, 0.0); IEnumerable <double> intersections = Radius.SolveRaytrace(surfaceFunction, z0, c); // The previous function returns a list of intersection distances. The value closest to 0.0f represents the // closest intersection point. double minimum = Single.PositiveInfinity; foreach (double i in intersections) { // Calculate the 3d point at which the ray intersects the cylinder: dvec3 intersectionPoint = rayStart + i * rayDirection; // Find the closest point to the intersectionPoint on the centerLine. // Get the vector v from the start of the cylinder to the intersection point: dvec3 v = intersectionPoint - start; // ...And project this vector onto the center line: double t = -dvec3.Dot(intersectionPoint, tangent * length) / (length * length); // Now we have the parameter t on the surface of the SymmetricCylinder at which the ray intersects. // Find the angle to the normal of the centerLine, so that we can determine whether the // angle is within the bound of the pie-slice at position t: dvec3 centerLineNormal = CenterCurve.GetNormalAt(t); dvec3 centerLineBinormal = CenterCurve.GetBinormalAt(t); dvec3 d = intersectionPoint - CenterCurve.GetPositionAt(t); double correctionShift = Math.Sign(dvec3.Dot(d, centerLineBinormal)); double phi = (correctionShift * Math.Acos(dvec3.Dot(d, centerLineNormal))) % (2.0 * Math.PI); // Determine if the ray is inside the pie-slice of the cylinder that is being displayed, // otherwise discard: if (phi > StartAngle.GetValueAt(t) && phi < EndAngle.GetValueAt(t) && i >= 0.0) { minimum = Math.Sign(i) * Math.Min(Math.Abs(minimum), Math.Abs(i)); } } return(minimum); }
/// <summary> /// Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product of x[i][j] and y[i][j]. /// Note: to get linear algebraic matrix multiplication, use the multiply operator (*). /// </summary> protected dmat3 matrixCompMult(dmat3 x, dmat3 y) { throw _invalidAccess; }
/// <summary> /// Returns a matrix that is the transpose of m. /// The input matrix m is not modified. /// </summary> protected dmat3 transpose(dmat3 m) { throw _invalidAccess; }
/// <summary>Returns the determinant of m. </summary> protected double determinant(dmat3 m) { throw _invalidAccess; }
/// <summary> /// Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product of x[i][j] and y[i][j]. /// Note: to get linear algebraic matrix multiplication, use the multiply operator (*). /// </summary> protected dmat3 matrixCompMult(dmat3 x, dmat3 y) { throw _invalidAccess; }
/// <summary>initialized the matrix with the upperleft part of m /// sets the lower right diagonal component(s) to 1, everything else to 0</summary> public dmat4(dmat3 m) { throw _invalidAccess; }
/// <summary>Returns the determinant of m. </summary> protected double determinant(dmat3 m) { throw _invalidAccess; }
/// <summary>initialized the matrix with the upperleft part of m /// sets the lower right diagonal component(s) to 1, everything else to 0</summary> public dmat4x3(dmat3 m) { throw _invalidAccess; }
/// <summary>initialized the matrix with the upperleft part of m /// sets the lower right diagonal component(s) to 1, everything else to 0</summary> public dmat3x4(dmat3 m) { throw _invalidAccess; }