Пример #1
0
        /// <summary>
        /// The method calculates the intersection area of triangle a and b both
        /// of type XYPolygon.
        /// </summary>
        /// <param name="triangleA">Triangle of type XYPolygon</param>
        /// <param name="triangleB">Triangle of type XYPolygon</param>
        /// <returns>
        ///	Intersection area between the triangles triangleA and triAngleB.
        /// </returns>
        protected static double TriangleIntersectionArea(XYPolygon triangleA, XYPolygon triangleB)
        {
            // TODO: Implement new algorithm - it is not very robust.
            // Consider an approach similar to the one used by DotSpatial and Java Topology Suite

            try
            {
                if (triangleA.Points.Count != 3 || triangleB.Points.Count != 3)
                {
                    throw new System.Exception("Argument must be a polygon with 3 points");
                }

                // TODO: implement an epsilon depending on the two triangles at hand.
                //XYExtent extentA = XYExtentUtil.GetExtent(triangleA);
                //XYExtent extentB = XYExtentUtil.GetExtent(triangleB);
                //double scalingLength
                //  = Math.Max(extentA.XMax - extentA.XMin,
                //    Math.Max(extentA.YMax - extentA.YMin,
                //    Math.Max(extentB.XMax - extentB.XMin, extentB.YMax - extentB.YMin)));
                //double epsilon = EPSILON * scalingLength;

                int i = 1;                                       // Index for "next" node in polygon a.
                int j = -1;                                      // Index for "next" node in polygon b.
                // -1 indicates that the first has not yet been found.
                double    area = 0;                              // Intersection area. Returned.
                XYPolygon intersectionPolygon = new XYPolygon(); // Intersection polygon.
                XYPoint   pFirst     = new XYPoint();            // First intersection point between triangles
                XYPoint   pIntersect = new XYPoint();            // Latest intersection node found

                pIntersect.X = triangleA.Points[0].X;
                pIntersect.Y = triangleA.Points[0].Y;
                Intersect(triangleA, triangleB, ref pIntersect, ref i, ref j, ref intersectionPolygon);
                pFirst = pIntersect;

                if (j != -1)
                {
                    int  jStop    = IncrementModula(j, 3);
                    bool complete = false;
                    int  count    = 0;
                    while (!complete)
                    {
                        // coordinates for vectors pointing to next triangleA and triangleB point respectively
                        double vax = triangleA.Points[i].X - pIntersect.X;
                        double vay = triangleA.Points[i].Y - pIntersect.Y;
                        double vbx = triangleB.Points[j].X - pIntersect.X;
                        double vby = triangleB.Points[j].Y - pIntersect.Y;

                        // The sideOf tells if the vb vector or the va vector is the one pointing "left"
                        // If sideOf is positive, vb is pointing left, otherwise va is pointing left
                        // The "left" vector is the one that is inside the polygon.
                        double sideOf = vax * vby - vay * vbx;

                        // Make sure to get out of EPSILON reach from the original point, hence 2*EPSILON
                        if (sideOf < 0 && IsPointInPolygon(pIntersect.X + 2 * EPSILON * vax, pIntersect.Y + 2 * EPSILON * vay, triangleB))
                        {
                            Intersect(triangleA, triangleB, ref pIntersect, ref i, ref j, ref intersectionPolygon);
                        }
                        else if (sideOf > 0 && IsPointInPolygon(pIntersect.X + 2 * EPSILON * vbx, pIntersect.Y + 2 * EPSILON * vby, triangleA))
                        {
                            Intersect(triangleB, triangleA, ref pIntersect, ref j, ref i, ref intersectionPolygon);
                        }
                        // can be true if the point is on the edge of the triangleB
                        // TODO: Replace with IsPointOnEdge of triangleB
                        else if (IsPointInPolygonOrOnEdge(pIntersect.X + 2 * EPSILON * vax, pIntersect.Y + 2 * EPSILON * vay, triangleB))
                        {
                            Intersect(triangleA, triangleB, ref pIntersect, ref i, ref j, ref intersectionPolygon);
                        }
                        // can be true if the point is on the edge of the triangleA
                        // Should never happen, since above test basically does the same
                        // TODO: Replace with IsPointOnEdge of triangleA
                        else if (IsPointInPolygonOrOnEdge(pIntersect.X + 2 * EPSILON * vbx, pIntersect.Y + 2 * EPSILON * vby, triangleA))
                        {
                            Intersect(triangleB, triangleA, ref pIntersect, ref j, ref i, ref intersectionPolygon);
                        }
                        else // triangleA and triangleB only touches one another but do not intersect
                        {
                            area = 0;
                            return(area);
                        }
                        if (intersectionPolygon.Points.Count > 1)
                        {
                            complete = (CalculatePointToPointDistance(pIntersect, pFirst) < EPSILON);
                        }
                        count++;
                        if (count > 20)
                        {
                            throw new System.Exception("Failed to find intersection polygon");
                        }
                    }
                    area = intersectionPolygon.GetArea();
                }
                else
                {
                    XYPoint pa = new XYPoint(); // internal point in triangle a
                    XYPoint pb = new XYPoint(); // internal point in triangle b

                    pa.X = (triangleA.GetX(0) + triangleA.GetX(1) + triangleA.GetX(2)) / 3;
                    pa.Y = (triangleA.GetY(0) + triangleA.GetY(1) + triangleA.GetY(2)) / 3;
                    pb.X = (triangleB.GetX(0) + triangleB.GetX(1) + triangleB.GetX(2)) / 3;
                    pb.Y = (triangleB.GetY(0) + triangleB.GetY(1) + triangleB.GetY(2)) / 3;

                    if (IsPointInPolygon(pa, triangleB) || IsPointInPolygon(pb, triangleA)) // triangleA is completely inside triangleB
                    {
                        area = Math.Min(triangleA.GetArea(), triangleB.GetArea());
                    }
                    else // triangleA and triangleB do dot intersect
                    {
                        area = 0;
                    }
                }
                return(area);
            }
            catch (System.Exception e)
            {
                throw new System.Exception("TriangleIntersectionArea failed", e);
            }
        }
        /// <summary>
        /// The method calculates the intersection area of triangle a and b both
        /// of type XYPolygon.
        /// </summary>
        /// <param name="triangleA">Triangle of type XYPolygon</param>
        /// <param name="triangleB">Triangle of type XYPolygon</param>
        /// <returns>
        ///	Intersection area between the triangles triangleA and triAngleB.
        /// </returns>
        protected static double TriangleIntersectionArea(XYPolygon triangleA, XYPolygon triangleB)
        {
            try
            {
                if (triangleA.Points.Count != 3 || triangleB.Points.Count != 3)
                {
                    throw new System.Exception("Argument must be a polygon with 3 points");
                }
                int i = 1;                                       // Index for "next" node in polygon a.
                int j = -1;                                      // Index for "next" node in polygon b.
                                                                 // -1 indicates that the first has not yet been found.
                double    area = 0;                              // Intersection area. Returned.
                XYPolygon intersectionPolygon = new XYPolygon(); // Intersection polygon.
                XYPoint   p = new XYPoint();                     // Latest intersection node found

                p.X = ((XYPoint)triangleA.Points[0]).X;
                p.Y = ((XYPoint)triangleA.Points[0]).Y;
                Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon);

                if (j != -1)
                {
                    // ERB 8/30/2012: For efficiency, allocate and initialize pFirst inside if block
                    XYPoint pFirst = new XYPoint(); // First intersection point between triangles
                    pFirst = p;
                    int  jStop    = Increase(j, 2);
                    bool complete = false;
                    int  count    = 0;
                    while (!complete)
                    {
                        // coordinates for vectors pointing to next triangleA and triangleB point respectively
                        double vax = ((XYPoint)triangleA.Points[i]).X - p.X;
                        double vay = ((XYPoint)triangleA.Points[i]).Y - p.Y;
                        double vbx = ((XYPoint)triangleB.Points[j]).X - p.X;
                        double vby = ((XYPoint)triangleB.Points[j]).Y - p.Y;

                        if (IsPointInPolygonOrOnEdge(p.X + EPSILON * vax, p.Y + EPSILON * vay, triangleB))
                        {
                            Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon);
                        }
                        else if (IsPointInPolygonOrOnEdge(p.X + EPSILON * vbx, p.Y + EPSILON * vby, triangleA))
                        {
                            Intersect(triangleB, triangleA, ref p, ref j, ref i, ref intersectionPolygon);
                        }
                        else // triangleA and triangleB only touches one another but do not intersect
                        {
                            area = 0;
                            return(area);
                        }
                        if (intersectionPolygon.Points.Count > 1)
                        {
                            complete = (CalculatePointToPointDistance(p, pFirst) < EPSILON);
                        }
                        count++;
                        if (count > 20)
                        {
                            throw new System.Exception("Failed to find intersection polygon");
                        }
                    }
                    area = intersectionPolygon.GetArea();
                }
                else
                {
                    XYPoint pa = new XYPoint(); // internal point in triangle a
                    XYPoint pb = new XYPoint(); // internal point in triangle b

                    pa.X = (triangleA.GetX(0) + triangleA.GetX(1) + triangleA.GetX(2)) / 3;
                    pa.Y = (triangleA.GetY(0) + triangleA.GetY(1) + triangleA.GetY(2)) / 3;
                    pb.X = (triangleB.GetX(0) + triangleB.GetX(1) + triangleB.GetX(2)) / 3;
                    pb.Y = (triangleB.GetY(0) + triangleB.GetY(1) + triangleB.GetY(2)) / 3;

                    if (IsPointInPolygon(pa, triangleB) || IsPointInPolygon(pb, triangleA)) // triangleA is completely inside triangleB
                    {
                        area = Math.Min(triangleA.GetArea(), triangleB.GetArea());
                    }
                    else // triangleA and triangleB do dot intersect
                    {
                        area = 0;
                    }
                }
                return(area);
            }
            catch (System.Exception e)
            {
                throw new System.Exception("TriangleIntersectionArea failed", e);
            }
        }
Пример #3
0
    /// <summary>
    /// The method calculates the intersection area of triangle a and b both
    /// of type XYPolygon.
    /// </summary>
    /// <param name="triangleA">Triangle of type XYPolygon</param>
    /// <param name="triangleB">Triangle of type XYPolygon</param>
    /// <returns>
    ///	Intersection area between the triangles triangleA and triAngleB.
    /// </returns>
    protected static double TriangleIntersectionArea(XYPolygon triangleA, XYPolygon triangleB)
    {
      try
      {
        if (triangleA.Points.Count != 3 || triangleB.Points.Count != 3)
        {
          throw new System.Exception("Argument must be a polygon with 3 points");
        }
        int i = 1;       // Index for "next" node in polygon a.
        int j = -1;      // Index for "next" node in polygon b. 
                         // -1 indicates that the first has not yet been found.
        double area = 0; // Intersection area. Returned.
        XYPolygon intersectionPolygon = new XYPolygon(); // Intersection polygon.
        XYPoint pFirst = new XYPoint(); // First intersection point between triangles
        XYPoint p = new XYPoint(); // Latest intersection node found

        p.X = ((XYPoint) triangleA.Points[0]).X;
        p.Y = ((XYPoint) triangleA.Points[0]).Y;
        Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon); 
        pFirst = p;

        if (j != -1)
        { 
          int jStop = Increase(j, 2);
          bool complete = false;
          int count = 0;
          while (!complete)
          {
            // coordinates for vectors pointing to next triangleA and triangleB point respectively
            double vax= ((XYPoint) triangleA.Points[i]).X - p.X;
            double vay= ((XYPoint) triangleA.Points[i]).Y - p.Y;
            double vbx= ((XYPoint) triangleB.Points[j]).X - p.X;
            double vby= ((XYPoint) triangleB.Points[j]).Y - p.Y;

            if(IsPointInPolygonOrOnEdge(p.X + EPSILON*vax, p.Y + EPSILON*vay, triangleB))
            {
              Intersect(triangleA, triangleB, ref p, ref i, ref j, ref intersectionPolygon);
            }
            else if(IsPointInPolygonOrOnEdge(p.X + EPSILON*vbx, p.Y + EPSILON*vby, triangleA))
            {
              Intersect(triangleB, triangleA, ref p, ref j, ref i, ref intersectionPolygon);
            }
            else // triangleA and triangleB only touches one another but do not intersect
            {
              area = 0;
              return area;
            }
            if (intersectionPolygon.Points.Count > 1)
            {
              complete = (CalculatePointToPointDistance(p, pFirst) < EPSILON);
            }
            count++;
            if ( count > 20 )
            {
              throw new System.Exception("Failed to find intersection polygon");
            }
          }
          area = intersectionPolygon.GetArea();
        }
        else
        {
          XYPoint pa = new XYPoint(); // internal point in triangle a
          XYPoint pb = new XYPoint(); // internal point in triangle b

          pa.X = (triangleA.GetX(0)+triangleA.GetX(1)+triangleA.GetX(2))/3;
          pa.Y = (triangleA.GetY(0)+triangleA.GetY(1)+triangleA.GetY(2))/3;
          pb.X = (triangleB.GetX(0)+triangleB.GetX(1)+triangleB.GetX(2))/3;
          pb.Y = (triangleB.GetY(0)+triangleB.GetY(1)+triangleB.GetY(2))/3;

          if (IsPointInPolygon(pa,triangleB) || IsPointInPolygon(pb,triangleA)) // triangleA is completely inside triangleB
          {
            area = Math.Min(triangleA.GetArea(),triangleB.GetArea());
          }
          else // triangleA and triangleB do dot intersect
          {
            area = 0;  
          }
        }
        return area;
      }
      catch (System.Exception e)
      {
        throw new System.Exception("TriangleIntersectionArea failed",e);
      }
    }