예제 #1
0
   bool Intersects(const Ray2 &ray, const Circle &circle, float *distance)
   {
      const Vector2 &rayDir = ray.GetDirection();

      // Adjust ray origin relative to circle center
      const Vector2 &rayOrig = ray.GetOrigin() - circle.GetCentre();
      float radius = circle.GetRadius();

      // Check origin inside first
      if (rayOrig.MagnitudeSquared() <= radius * radius)
      {
         SetPtrValue(distance, 0.0f);
         return true;
      }

      // Mmm, quadratics
      // Build coeffs which can be used with std quadratic solver
      // ie t = (-b +/- sqrt(b * b + 4ac)) / 2a
      float a = Vector2::DotProduct(rayDir, rayDir);
      float b = 2 * Vector2::DotProduct(rayOrig, rayDir);
      float c = Vector2::DotProduct(rayOrig, rayOrig) - radius * radius;

      // Calc determinant
      float d = (b * b) - (4 * a * c);
      if (d < 0)
      {
         // No intersection
         SetPtrValue(distance, 0.0f);
         return false;
      }
      else
      {
         // BTW, if d=0 there is one intersection, if d > 0 there are 2
         // But we only want the closest one, so that's ok, just use the 
         // '-' version of the solver

         float negB(-b);
         float sqrtD(Sqrt(d));
         float twoA(2 * a);

         float t = (negB - sqrtD) / twoA;

         if (t < 0)
         {
            t = (negB + sqrtD) / twoA;
         }

         if (t > 0)
         {
            SetPtrValue(distance, t);
            return true;
         }

         return false;
      }
   }
예제 #2
0
   bool Intersects(const LineSegment2 &lineSegment, bool singleSided, const Ray2 &ray, float *distance)
   {
      if (singleSided && Vector2::DotProduct(ray.GetDirection(), lineSegment.GetNormal()) >= 0.0f)
      {
         // Ray is pointing in the same direction as the line normal
         return false;
      }

      const Vector2 &P0 = ray.GetOrigin();
      const Vector2 &D0 = ray.GetDirection();
      const Vector2 &P1 = lineSegment.GetTail();
      const Vector2 &D1 = lineSegment.GetVector();

      Vector2 perpD0 = Perp(D0);
      Vector2 perpD1 = Perp(D1);

      if (Dot(perpD1, D0) != 0.0f)
      {
         Vector2 P1MinusP0 = P1 - P0;
         float s = Dot(perpD1, P1MinusP0) / Dot(perpD1,D0);
         float t = Dot(perpD0, P1MinusP0) / Dot(perpD1,D0);
         bool intersects = s >= 0.0f && 0.0f <= t && t <= 1.0f;

         if (intersects)
         {
            if (distance)
            {
               // We've probably already calculated the nearest point in terms of s & t but
               // I can't figure it out.
               
               *distance = s; // ((lineSegment.GetTail() + lineSegment.GetDirection() * t) - ray.GetOrigin()).Magnitude();
               // *distance = (nearestPoint - ray.GetOrigin()).Magnitude();
            }

            return true;
         }
      }

      return false;
   }
예제 #3
0
//----------------------------------------------------------------------------
bool Mgc::FindIntersection (const Ray2& rkRay0, const Ray2& rkRay1,
    int& riQuantity, Real afT[2])
{
    Vector2 kDiff;
    Real fD0SqrLen;
    bool bIntersects = Find(rkRay0.Origin(),rkRay0.Direction(),
        rkRay1.Origin(),rkRay1.Direction(),kDiff,fD0SqrLen,riQuantity,afT);

    if ( bIntersects )
    {
        if ( riQuantity == 1 )
        {
            if ( afT[0] < 0.0f || afT[1] < 0.0f )
            {
                // lines intersect, but rays do not
                riQuantity = 0;
            }
        }
        else
        {
            // rays are on same line
            Real fDot = kDiff.Dot(rkRay0.Direction());
            if ( rkRay0.Direction().Dot(rkRay1.Direction()) > 0.0f )
            {
                // Rays point in same direction, get semiinfinite interval
                // of intersection.
                afT[0] = ( fDot >= 0.0f ? fDot/fD0SqrLen : 0.0f );
                afT[1] = Math::MAX_REAL;
            }
            else
            {
                // test for overlap of opposite pointing rays
                if ( fDot > 0.0f )
                {
                    afT[0] = 0.0f;
                    afT[1] = fDot/fD0SqrLen;
                }
                else if ( fDot < 0.0f )
                {
                    // no overlap
                    riQuantity = 0;
                }
                else
                {
                    // rays have a common origin
                    riQuantity = 1;
                    afT[0] = 0.0f;
                }
            }
        }
    }

    return riQuantity != 0;
}
예제 #4
0
//----------------------------------------------------------------------------
bool Mgc::FindIntersection (const Line2& rkLine, const Ray2& rkRay,
    int& riQuantity, Real afT[2])
{
    Vector2 kDiff;
    Real fD0SqrLen;
    bool bIntersects = Find(rkLine.Origin(),rkLine.Direction(),
        rkRay.Origin(),rkRay.Direction(),kDiff,fD0SqrLen,riQuantity,afT);

    if ( bIntersects )
    {
        if ( riQuantity == 1 )
        {
            if ( afT[1] < 0.0f )
            {
                // lines intersect, but ray does not intersect line
                riQuantity = 0;
            }
        }
        else
        {
            // ray is contained by line, adjust intersection interval
            if ( rkLine.Direction().Dot(rkRay.Direction()) > 0.0f )
            {
                afT[0] = (kDiff.Dot(rkLine.Direction()))/fD0SqrLen;
                afT[1] = Math::MAX_REAL;
            }
            else
            {
                afT[0] = -Math::MAX_REAL;
                afT[1] = (kDiff.Dot(rkLine.Direction()))/fD0SqrLen;
            }
        }
    }

    return riQuantity != 0;
}
예제 #5
0
파일: T2lRay2.cpp 프로젝트: ta2la/geogebra
//=============================================================================
bool Ray2::intersectParam( const Ray2& ray1, const Ray2& ray2, double& parameter, bool onlyExistence)
{
    double determinant = ray1.getDir().x()*ray2.getDir().y() - ray1.getDir().y()*ray2.getDir().x();
    bool exists = true;
    if ( ( determinant > -10e-12 ) && ( determinant <  10e-12 ) ) exists = false;
    if (exists == false) return false;

    if (onlyExistence) return exists;

    Vector2F delta( ray2.origin_, ray1.origin_);
    parameter = ( delta.y()*ray2.getDir().x() - delta.x()*ray2.getDir().y() ) / determinant;
    return true;
}
예제 #6
0
//----------------------------------------------------------------------------
bool Mgc::FindIntersection (const Ray2& rkRay, const Segment2& rkSegment,
    int& riQuantity, Real afT[2])
{
    Vector2 kDiff;
    Real fD0SqrLen;
    bool bIntersects = Find(rkRay.Origin(),rkRay.Direction(),
        rkSegment.Origin(),rkSegment.Direction(),kDiff,fD0SqrLen,riQuantity,
        afT);

    if ( bIntersects )
    {
        if ( riQuantity == 1 )
        {
            if ( afT[0] < 0.0f || afT[1] < 0.0f || afT[1] > 1.0f )
            {
                // lines intersect, but ray and segment do not
                riQuantity = 0;
            }
        }
        else
        {
            // ray and segment are on the same line
            Real fDotRS = rkRay.Direction().Dot(rkSegment.Direction());
            Real fDot0, fDot1;
            if ( fDotRS > 0.0f )
            {
                fDot0 = kDiff.Dot(rkRay.Direction());
                fDot1 = fDot0 + fDotRS;
            }
            else
            {
                fDot1 = kDiff.Dot(rkRay.Direction());
                fDot0 = fDot1 + fDotRS;
            }

            // compute intersection of [t0,t1] and [0,+infinity]
            if ( fDot0 >= 0.0f )
            {
                // complete overlap
                Real fInvLen = 1.0f/fD0SqrLen;
                afT[0] = fDot0*fInvLen;
                afT[1] = fDot1*fInvLen;
            }
            else if ( fDot1 > 0.0f )
            {
                // partial overlap
                afT[0] = 0.0f;
                afT[1] = fDot1/fD0SqrLen;
            }
            else if ( fDot1 < 0.0f )
            {
                // no overlap
                riQuantity = 0;
            }
            else
            {
                // overlap at a single end point
                riQuantity = 1;
                afT[0] = 0.0f;
            }
        }
    }

    return riQuantity != 0;
}
예제 #7
0
 Vector2 operator*(const Ray2 &ray, float distance)
 {
    return Vector2(ray.GetOrigin() + ray.GetDirection() * distance);
 }
예제 #8
0
   // Ray Intersection
   bool Intersects(const Ray2 &ray, const AARect &rect, float *distance)
   {
      if (rect.IsNull()) 
      {
         SetPtrValue(distance, 0.0f);
         return false;
      }

      float lowt = 0.0f;
      float t;
      bool hit = false;
      Vector2 hitpoint;
      const Vector2 &rectMin = rect.GetMinimum();
      const Vector2 &rectMax = rect.GetMaximum();
      const Vector2 &rayOrig = ray.GetOrigin();
      const Vector2 &rayDir = ray.GetDirection();

      // Check origin inside first
      if (rayOrig.x > rectMin.x && rayOrig.y > rectMin.y && rayOrig.x < rectMax.x && rayOrig.y < rectMax.y)
      {
         SetPtrValue(distance, 0.0f);
         return true;
      }

      // Check each face in turn, only check closest 3
      // Min x
      if (rayOrig.x < rectMin.x && rayDir.x > 0)
      {
         t = (rectMin.x - rayOrig.x) / rayDir.x;

         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.y >= rectMin.y && hitpoint.y <= rectMax.y /* && (!hit || t < lowt) */)
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }
      // Max x
      if (rayOrig.x > rectMax.x && rayDir.x < 0)
      {
         t = (rectMax.x - rayOrig.x) / rayDir.x;
         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.y >= rectMin.y && hitpoint.y <= rectMax.y &&
               (!hit || t < lowt))
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }
      // Min y
      if (rayOrig.y < rectMin.y && rayDir.y > 0)
      {
         t = (rectMin.y - rayOrig.y) / rayDir.y;
         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.x >= rectMin.x && hitpoint.x <= rectMax.x &&
               (!hit || t < lowt))
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }
      // Max y
      if (rayOrig.y > rectMax.y && rayDir.y < 0)
      {
         t = (rectMax.y - rayOrig.y) / rayDir.y;
         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.x >= rectMin.x && hitpoint.x <= rectMax.x &&
               (!hit || t < lowt))
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }

      SetPtrValue(distance, lowt);
      return hit;
   }