protected void CalculateFactors(IElementSet elementSet)
 {
     for (int i = 0; i < elementSet.ElementCount; i++)
     {
         XYPolygon element = ElementMapper.CreateXYPolygon(elementSet, i);
         double    area    = element.GetArea();
         if (_areaExponent == 1)
         {
             _factors[i] = area;
         }
         else if (_areaExponent == -1)
         {
             _factors[i] = 1.0 / area;
         }
         else
         {
             _factors[i] = Math.Pow(area, _areaExponent);
         }
     }
 }
Ejemplo n.º 2
0
		public void GetArea()
		{
			// -- Rectangle --
			XYPolygon xypolygon = new XYPolygon();
			xypolygon.Points.Add(new XYPoint(1,1));
			xypolygon.Points.Add(new XYPoint(9,1));
			xypolygon.Points.Add(new XYPoint(9,6));
			xypolygon.Points.Add(new XYPoint(1,6));
			Assert.AreEqual((double) 40, xypolygon.GetArea());

			// -- Triangle -- 
			XYPolygon xypolygon2 = new XYPolygon();
			xypolygon2.Points.Add(new XYPoint(1,1));
			xypolygon2.Points.Add(new XYPoint(9,1));
			xypolygon2.Points.Add(new XYPoint(9,6));
			Assert.AreEqual((double) 20, xypolygon2.GetArea());

			// -- concave --
			XYPolygon xypolygon3 = new XYPolygon();
			xypolygon3.Points.Add(new XYPoint(1,1));
			xypolygon3.Points.Add(new XYPoint(5,3));
			xypolygon3.Points.Add(new XYPoint(9,1));
			xypolygon3.Points.Add(new XYPoint(9,6));
			xypolygon3.Points.Add(new XYPoint(1,6));
			Assert.AreEqual((double) 32, xypolygon3.GetArea());

			// -- concave --
			XYPolygon xypolygon4 = new XYPolygon();
			xypolygon4.Points.Add(new XYPoint(1,1));
			xypolygon4.Points.Add(new XYPoint(9,1));
			xypolygon4.Points.Add(new XYPoint(5,5));
			xypolygon4.Points.Add(new XYPoint(5,3));
			xypolygon4.Points.Add(new XYPoint(3,3));
			xypolygon4.Points.Add(new XYPoint(3,8));
			xypolygon4.Points.Add(new XYPoint(9,8));
			xypolygon4.Points.Add(new XYPoint(9,11));
			xypolygon4.Points.Add(new XYPoint(1,11));
			Assert.AreEqual((double) 50, xypolygon4.GetArea());
		}
Ejemplo n.º 3
0
        /// <summary>
        /// Calculates the mapping matrix between fromElements and toElements. The mapping method
        /// is decided from the combination of methodDescription, fromElements.ElementType and
        /// toElements.ElementType.
        /// The valid values for methodDescription is obtained through use of the
        /// GetAvailableMethods method.
        /// </summary>
        ///
        /// <remarks>
        /// UpdateMappingMatrix is called during initialisation. UpdateMappingMatrix must be called prior
        /// to Mapvalues.
        /// </remarks>
        ///
        /// <param name="methodIdentifier">String identification of mapping method</param>
        /// <param name="fromElements">The IElementset to map from.</param>
        /// <param name="toElements">The IElementset to map to</param>
        ///
        /// <returns>
        /// The method has no return value.
        /// </returns>
        private void UpdateMappingMatrix(ref IIdentifiable methodIdentifier, ref IElementSet fromElements, ref IElementSet toElements)
        {
            try
            {
                ElementSetChecker.CheckElementSet(fromElements);
                ElementSetChecker.CheckElementSet(toElements);

                _method              = SpatialAdaptedOutputFactory.GetMethod(methodIdentifier);
                _numberOfToRows      = toElements.ElementCount;
                _numberOfFromColumns = fromElements.ElementCount;
                _mappingMatrix       = new DoubleSparseMatrix(_numberOfToRows, _numberOfFromColumns);

                if (fromElements.ElementType == ElementType.Point && toElements.ElementType == ElementType.Point)
                {
                    #region

                    try
                    {
                        for (int i = 0; i < _numberOfToRows; i++)
                        {
                            XYPoint toPoint = CreateXYPoint(toElements, i);
                            for (int j = 0; j < _numberOfFromColumns; j++)
                            {
                                XYPoint fromPoint = CreateXYPoint(fromElements, j);
                                _mappingMatrix[i, j] = XYGeometryTools.CalculatePointToPointDistance(toPoint, fromPoint);
                            }
                        }

                        if (_method == ElementMapperMethod.Nearest)
                        {
                            for (int i = 0; i < _numberOfToRows; i++)
                            {
                                double minDist = _mappingMatrix[i, 0];
                                for (int j = 1; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] < minDist)
                                    {
                                        minDist = _mappingMatrix[i, j];
                                    }
                                }
                                int denominator = 0;
                                for (int j = 0; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] == minDist)
                                    {
                                        _mappingMatrix[i, j] = 1;
                                        denominator++;
                                    }
                                    else
                                    {
                                        _mappingMatrix[i, j] = 0;
                                    }
                                }
                                for (int j = 0; j < _numberOfFromColumns; j++)
                                {
                                    _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                }
                            }
                        }
                        else if (_method == ElementMapperMethod.Inverse)
                        {
                            for (int i = 0; i < _numberOfToRows; i++)
                            {
                                double minDist = _mappingMatrix[i, 0];
                                for (int j = 1; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] < minDist)
                                    {
                                        minDist = _mappingMatrix[i, j];
                                    }
                                }
                                if (minDist == 0)
                                {
                                    int denominator = 0;
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        if (_mappingMatrix[i, j] == minDist)
                                        {
                                            _mappingMatrix[i, j] = 1;
                                            denominator++;
                                        }
                                        else
                                        {
                                            _mappingMatrix[i, j] = 0;
                                        }
                                    }
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                    }
                                }
                                else
                                {
                                    double denominator = 0;
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = 1 / _mappingMatrix[i, j];
                                        denominator          = denominator + _mappingMatrix[i, j];
                                    }
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                    }
                                }
                            }
                        }
                        else
                        {
                            throw new Exception("methodDescription unknown for point point mapping");
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Point to point mapping failed", e);
                    }

                    #endregion
                }
                else if (fromElements.ElementType == ElementType.Point && toElements.ElementType == ElementType.PolyLine)
                {
                    #region

                    try
                    {
                        for (int i = 0; i < _numberOfToRows; i++)
                        {
                            XYPolyline toPolyLine = CreateXYPolyline(toElements, i);
                            for (int j = 0; j < _numberOfFromColumns; j++)
                            {
                                XYPoint fromPoint = CreateXYPoint(fromElements, j);
                                _mappingMatrix[i, j] = XYGeometryTools.CalculatePolylineToPointDistance(toPolyLine,
                                                                                                        fromPoint);
                            }
                        }

                        if (_method == ElementMapperMethod.Nearest)
                        {
                            for (int i = 0; i < _numberOfToRows; i++)
                            {
                                double minDist = _mappingMatrix[i, 0];
                                for (int j = 1; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] < minDist)
                                    {
                                        minDist = _mappingMatrix[i, j];
                                    }
                                }
                                int denominator = 0;
                                for (int j = 0; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] == minDist)
                                    {
                                        _mappingMatrix[i, j] = 1;
                                        denominator++;
                                    }
                                    else
                                    {
                                        _mappingMatrix[i, j] = 0;
                                    }
                                }
                                for (int j = 0; j < _numberOfFromColumns; j++)
                                {
                                    _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                }
                            }
                        }
                        else if (_method == ElementMapperMethod.Inverse)
                        {
                            for (int i = 0; i < _numberOfToRows; i++)
                            {
                                double minDist = _mappingMatrix[i, 0];
                                for (int j = 1; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] < minDist)
                                    {
                                        minDist = _mappingMatrix[i, j];
                                    }
                                }
                                if (minDist == 0)
                                {
                                    int denominator = 0;
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        if (_mappingMatrix[i, j] == minDist)
                                        {
                                            _mappingMatrix[i, j] = 1;
                                            denominator++;
                                        }
                                        else
                                        {
                                            _mappingMatrix[i, j] = 0;
                                        }
                                    }
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                    }
                                }
                                else
                                {
                                    double denominator = 0;
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = 1 / _mappingMatrix[i, j];
                                        denominator          = denominator + _mappingMatrix[i, j];
                                    }
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                    }
                                }
                            }
                        }
                        else
                        {
                            throw new Exception("methodDescription unknown for point to polyline mapping");
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Point to polyline mapping failed", e);
                    }

                    #endregion
                }
                else if (fromElements.ElementType == ElementType.Point &&
                         toElements.ElementType == ElementType.Polygon)
                {
                    #region

                    try
                    {
                        for (int i = 0; i < _numberOfToRows; i++)
                        {
                            XYPolygon polygon = CreateXYPolygon(toElements, i);
                            int       count   = 0;
                            XYPoint   point;
                            for (int n = 0; n < _numberOfFromColumns; n++)
                            {
                                point = CreateXYPoint(fromElements, n);
                                if (XYGeometryTools.IsPointInPolygon(point, polygon))
                                {
                                    if (_method == ElementMapperMethod.Mean)
                                    {
                                        count = count + 1;
                                    }
                                    else if (_method == ElementMapperMethod.Sum)
                                    {
                                        count = 1;
                                    }
                                    else
                                    {
                                        throw new Exception(
                                                  "methodDescription unknown for point to polygon mapping");
                                    }
                                }
                            }
                            for (int n = 0; n < _numberOfFromColumns; n++)
                            {
                                point = CreateXYPoint(fromElements, n);

                                if (XYGeometryTools.IsPointInPolygon(point, polygon))
                                {
                                    _mappingMatrix[i, n] = 1.0 / count;
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Point to polygon mapping failed", e);
                    }

                    #endregion
                }
                else if (fromElements.ElementType == ElementType.PolyLine &&
                         toElements.ElementType == ElementType.Point)
                {
                    #region

                    try
                    {
                        for (int i = 0; i < _numberOfToRows; i++)
                        {
                            XYPoint toPoint = CreateXYPoint(toElements, i);
                            for (int j = 0; j < _numberOfFromColumns; j++)
                            {
                                XYPolyline fromPolyLine = CreateXYPolyline(fromElements, j);
                                _mappingMatrix[i, j] =
                                    XYGeometryTools.CalculatePolylineToPointDistance(fromPolyLine, toPoint);
                            }
                        }

                        if (_method == ElementMapperMethod.Nearest)
                        {
                            for (int i = 0; i < _numberOfToRows; i++)
                            {
                                double minDist = _mappingMatrix[i, 0];
                                for (int j = 1; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] < minDist)
                                    {
                                        minDist = _mappingMatrix[i, j];
                                    }
                                }
                                int denominator = 0;
                                for (int j = 0; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] == minDist)
                                    {
                                        _mappingMatrix[i, j] = 1;
                                        denominator++;
                                    }
                                    else
                                    {
                                        _mappingMatrix[i, j] = 0;
                                    }
                                }
                                for (int j = 0; j < _numberOfFromColumns; j++)
                                {
                                    _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                }
                            }
                        }
                        else if (_method == ElementMapperMethod.Inverse)
                        {
                            for (int i = 0; i < _numberOfToRows; i++)
                            {
                                double minDist = _mappingMatrix[i, 0];
                                for (int j = 1; j < _numberOfFromColumns; j++)
                                {
                                    if (_mappingMatrix[i, j] < minDist)
                                    {
                                        minDist = _mappingMatrix[i, j];
                                    }
                                }
                                if (minDist == 0)
                                {
                                    int denominator = 0;
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        if (_mappingMatrix[i, j] == minDist)
                                        {
                                            _mappingMatrix[i, j] = 1;
                                            denominator++;
                                        }
                                        else
                                        {
                                            _mappingMatrix[i, j] = 0;
                                        }
                                    }
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                    }
                                }
                                else
                                {
                                    double denominator = 0;
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = 1 / _mappingMatrix[i, j];
                                        denominator          = denominator + _mappingMatrix[i, j];
                                    }
                                    for (int j = 0; j < _numberOfFromColumns; j++)
                                    {
                                        _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                    }
                                }
                            }
                        }
                        else
                        {
                            throw new Exception("methodDescription unknown for polyline to point mapping");
                        }
                    }
                    catch (Exception e) // Catch for all of the Point to Polyline part
                    {
                        throw new Exception("Polyline to point mapping failed", e);
                    }

                    #endregion
                }
                else if (fromElements.ElementType == ElementType.PolyLine &&
                         toElements.ElementType == ElementType.Polygon)
                {
                    #region

                    try
                    {
                        // For each polygon in target
                        for (int i = 0; i < _numberOfToRows; i++)
                        {
                            XYPolygon polygon = CreateXYPolygon(toElements, i);

                            if (_method == ElementMapperMethod.WeightedMean)
                            {
                                double totalLineLengthInPolygon = 0;
                                for (int n = 0; n < _numberOfFromColumns; n++)
                                {
                                    XYPolyline polyline = CreateXYPolyline(fromElements, n);
                                    _mappingMatrix[i, n] =
                                        XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(
                                            polyline, polygon);
                                    totalLineLengthInPolygon += _mappingMatrix[i, n];
                                }
                                if (totalLineLengthInPolygon > 0)
                                {
                                    for (int n = 0; n < _numberOfFromColumns; n++)
                                    {
                                        _mappingMatrix[i, n] = _mappingMatrix[i, n] /
                                                               totalLineLengthInPolygon;
                                    }
                                }
                            }
                            else if (_method == ElementMapperMethod.WeightedSum)
                            {
                                // For each line segment in PolyLine
                                for (int n = 0; n < _numberOfFromColumns; n++)
                                {
                                    XYPolyline polyline = CreateXYPolyline(fromElements, n);
                                    _mappingMatrix[i, n] =
                                        XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(
                                            polyline, polygon) / polyline.GetLength();
                                }
                            }
                            else
                            {
                                throw new Exception(
                                          "methodDescription unknown for polyline to polygon mapping");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Polyline to polygon mapping failed", e);
                    }

                    #endregion
                }
                else if (fromElements.ElementType == ElementType.Polygon &&
                         toElements.ElementType == ElementType.Point)
                {
                    #region

                    try
                    {
                        if (_method != ElementMapperMethod.Value)
                        {
                            throw new Exception("methodDescription unknown for polygon to point mapping");
                        }

                        // Only create search tree if number of cols/rows is larger than say 10/10.
                        bool useSearchTree = _numberOfFromColumns > 10 && _numberOfToRows > 10;
                        XYElementSearchTree <int> fromSearchTree     = null;
                        ICollection <int>         fromCandidateElmts = null;
                        if (useSearchTree)
                        {
                            fromSearchTree = XYElementSearchTree <int> .BuildSearchTree(fromElements);
                        }
                        else
                        {
                            fromCandidateElmts = new IntSequence(0, _numberOfFromColumns - 1);
                        }

                        for (int n = 0; n < _numberOfToRows; n++)
                        {
                            XYPoint point = CreateXYPoint(toElements, n);
                            if (useSearchTree)
                            {
                                XYExtent toExtent = XYExtentUtil.GetExtent(point, XYGeometryTools.EPSILON);
                                fromCandidateElmts = fromSearchTree.FindElements(toExtent);
                            }

                            int count = 0;

                            // Check first for strict inclusion
                            foreach (int i in fromCandidateElmts)
                            {
                                XYPolygon polygon = CreateXYPolygon(fromElements, i);
                                if (XYGeometryTools.IsPointInPolygon(point, polygon))
                                {
                                    _mappingMatrix[n, i] = 1.0;
                                    count++;
                                }
                            }
                            if (count == 0)
                            {
                                // Not strictly inside any polygon, check also edges
                                foreach (int i in fromCandidateElmts)
                                {
                                    XYPolygon polygon = CreateXYPolygon(fromElements, i);
                                    if (XYGeometryTools.IsPointInPolygonOrOnEdge(point, polygon))
                                    {
                                        _mappingMatrix[n, i] = 1.0;
                                        count++;
                                    }
                                }
                            }
                            if (count > 1)
                            {
                                // In case of more than one hit, use average
                                foreach (int i in fromCandidateElmts)
                                {
                                    if (_mappingMatrix[n, i] != 0.0)
                                    {
                                        _mappingMatrix[n, i] = 1.0 / count;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Polygon to point mapping failed", e);
                    }

                    #endregion
                }
                else if (fromElements.ElementType == ElementType.Polygon &&
                         toElements.ElementType == ElementType.PolyLine)
                // Polygon to PolyLine
                {
                    #region

                    try
                    {
                        for (int i = 0; i < _numberOfToRows; i++)
                        {
                            XYPolyline polyline = CreateXYPolyline(toElements, i);

                            if (_method == ElementMapperMethod.WeightedMean)
                            {
                                for (int n = 0; n < _numberOfFromColumns; n++)
                                {
                                    XYPolygon polygon = CreateXYPolygon(fromElements, n);
                                    _mappingMatrix[i, n] =
                                        XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(
                                            polyline, polygon) / polyline.GetLength();
                                }
                                double sum = 0;
                                for (int n = 0; n < _numberOfFromColumns; n++)
                                {
                                    sum += _mappingMatrix[i, n];
                                }
                                for (int n = 0; n < _numberOfFromColumns; n++)
                                {
                                    _mappingMatrix[i, n] = _mappingMatrix[i, n] / sum;
                                }
                            }
                            else if (_method == ElementMapperMethod.WeightedSum)
                            {
                                for (int n = 0; n < _numberOfFromColumns; n++)
                                {
                                    XYPolygon polygon = CreateXYPolygon(fromElements, n);
                                    _mappingMatrix[i, n] =
                                        XYGeometryTools.CalculateLengthOfPolylineInsidePolygon(
                                            polyline, polygon) / polyline.GetLength();
                                }
                            }
                            else
                            {
                                throw new Exception(
                                          "methodDescription unknown for polygon to polyline mapping");
                            }
                        }
                    }
                    catch (Exception e) // catch for all of Polygon to PolyLine
                    {
                        throw new Exception("Polygon to polyline mapping failed", e);
                    }

                    #endregion
                }
                else if (fromElements.ElementType == ElementType.Polygon &&
                         toElements.ElementType == ElementType.Polygon)
                // Polygon to Polygon
                {
                    #region

                    try
                    {
                        // Only create search tree if number of cols/rows is larger than say 100/10.
                        bool useSearchTree = _numberOfFromColumns > 10 && _numberOfToRows > 10;
                        XYElementSearchTree <int> fromSearchTree     = null;
                        ICollection <int>         fromCandidateElmts = null;
                        if (useSearchTree)
                        {
                            fromSearchTree = XYElementSearchTree <int> .BuildSearchTree(fromElements);
                        }
                        else
                        {
                            fromCandidateElmts = new IntSequence(0, _numberOfFromColumns - 1);
                        }

                        for (int i = 0; i < _numberOfToRows; i++)
                        {
                            XYPolygon toPolygon = CreateXYPolygon(toElements, i);
                            if (useSearchTree)
                            {
                                XYExtent toExtent = XYExtentUtil.GetExtent(toPolygon);
                                fromCandidateElmts = fromSearchTree.FindElements(toExtent);
                            }

                            foreach (int j in fromCandidateElmts)
                            {
                                XYPolygon fromPolygon = CreateXYPolygon(fromElements, j);
                                _mappingMatrix[i, j] = XYGeometryTools.CalculateSharedArea(
                                    toPolygon, fromPolygon);
                                if (_method == ElementMapperMethod.Distribute)
                                {
                                    _mappingMatrix[i, j] /= fromPolygon.GetArea();
                                }
                            }

                            if (_method == ElementMapperMethod.WeightedMean)
                            {
                                double denominator = 0;
                                foreach (int j in fromCandidateElmts)
                                {
                                    denominator = denominator + _mappingMatrix[i, j];
                                }
                                foreach (int j in fromCandidateElmts)
                                {
                                    if (denominator != 0)
                                    {
                                        _mappingMatrix[i, j] = _mappingMatrix[i, j] / denominator;
                                    }
                                }
                            }
                            else if (_method == ElementMapperMethod.WeightedSum)
                            {
                                foreach (int j in fromCandidateElmts)
                                {
                                    _mappingMatrix[i, j] = _mappingMatrix[i, j] / toPolygon.GetArea();
                                }
                            }
                            else if (_method != ElementMapperMethod.Distribute)
                            {
                                throw new Exception(
                                          "methodDescription unknown for polygon to polygon mapping");
                            }
                        }
                    }
                    catch (Exception e) // catch for all of Polygon to Polygon
                    {
                        throw new Exception("Polygon to polygon mapping failed", e);
                    }

                    #endregion
                }
                else // if the fromElementType, toElementType combination is no implemented
                {
                    throw new Exception(
                              "Mapping of specified ElementTypes not included in ElementMapper");
                }
            }
            catch (Exception e)
            {
                throw new Exception("UpdateMappingMatrix failed to update mapping matrix", 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);
            }
        }
Ejemplo n.º 5
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);
            }
        }
Ejemplo n.º 6
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);
      }
    }
		public void Protected_TriangleIntersectionArea()
		{
			XYPolygon t1 = new XYPolygon();
			t1.Points.Add(new XYPoint(0.0, 0.5));
			t1.Points.Add(new XYPoint(6.0, 0.5));
			t1.Points.Add(new XYPoint(1.0, 7.0));

			XYPolygon t2 = new XYPolygon();
      t2.Points.Add(new XYPoint(1,1));
			t2.Points.Add(new XYPoint(5,1));
			t2.Points.Add(new XYPoint(1,5));

			XYPolygon t3 = new XYPolygon();
      t3.Points.Add(new XYPoint(1,1));
			t3.Points.Add(new XYPoint(3,1));
			t3.Points.Add(new XYPoint(1,3));

			XYPolygon t4 = new XYPolygon();
      t4.Points.Add(new XYPoint(1,2));
			t4.Points.Add(new XYPoint(3,2));
			t4.Points.Add(new XYPoint(3,4));

			XYPolygon t5 = new XYPolygon();
      t5.Points.Add(new XYPoint(6.5,3.5));
			t5.Points.Add(new XYPoint(9.5,3.4));
			t5.Points.Add(new XYPoint(7,5));

      XYPolygon t6 = new XYPolygon();
      t6.Points.Add(new XYPoint(-2,0));
      t6.Points.Add(new XYPoint(3,0));
      t6.Points.Add(new XYPoint(3,2));

			//t2 is fully inside t1	
			Assert.AreEqual(8,AXYGeometryTools.ATriangleIntersectionArea(t2,t1),"t2, t1");
      Assert.AreEqual(8,AXYGeometryTools.ATriangleIntersectionArea(t1,t2),"t1, t2");

			// t4 is partly inside t2
			Assert.AreEqual((double)7/ (double) 4, AXYGeometryTools.ATriangleIntersectionArea(t2,t4),"t2, t4");
      Assert.AreEqual((double)7/ (double) 4, AXYGeometryTools.ATriangleIntersectionArea(t4,t2),"t4, t2");

			// t3 is inside t2 but is sharing two edges
    	Assert.AreEqual(2, AXYGeometryTools.ATriangleIntersectionArea(t2,t3),"t2, t3");
    	Assert.AreEqual(2, AXYGeometryTools.ATriangleIntersectionArea(t3,t2),"t3, t2");

			// t1 and t5 has no overlap
			Assert.AreEqual(0, AXYGeometryTools.ATriangleIntersectionArea(t1,t5),"t1, t5");
			Assert.AreEqual(0, AXYGeometryTools.ATriangleIntersectionArea(t5,t1),"t5, t1");

      // two times t6
      Assert.AreEqual(t6.GetArea(), AXYGeometryTools.ATriangleIntersectionArea(t6,t6),"t6, t6");
		}
    public void CalculateSharedArea()
    {
      XYPolygon p1 = new XYPolygon();
      p1.Points.Add(new XYPoint(0, 3));
      p1.Points.Add(new XYPoint(3, 0));
      p1.Points.Add(new XYPoint(8, 0));
      p1.Points.Add(new XYPoint(8, 2));
      p1.Points.Add(new XYPoint(3, 1));
      p1.Points.Add(new XYPoint(3, 3));
      p1.Points.Add(new XYPoint(8, 3));
      p1.Points.Add(new XYPoint(4, 7));

      XYPolygon p2 = new XYPolygon();
      p2.Points.Add(new XYPoint(3, 3));
      p2.Points.Add(new XYPoint(4, 3));
      p2.Points.Add(new XYPoint(4, 4));
      p2.Points.Add(new XYPoint(3, 4));

      XYPolygon p3 = new XYPolygon();
      p3.Points.Add(new XYPoint(0, 0));
      p3.Points.Add(new XYPoint(8, 0));
      p3.Points.Add(new XYPoint(8, 8));
      p3.Points.Add(new XYPoint(0, 8));

      XYPolygon p4 = new XYPolygon();
      p4.Points.Add(new XYPoint(-2, 0));
      p4.Points.Add(new XYPoint(3, 0));
      p4.Points.Add(new XYPoint(3, 2));
      p4.Points.Add(new XYPoint(0, 2));
      p4.Points.Add(new XYPoint(0, 5));
      p4.Points.Add(new XYPoint(4, 5));
      p4.Points.Add(new XYPoint(4, 7));
      p4.Points.Add(new XYPoint(-2, 7));

      Assert.AreEqual(p1.GetArea(),XYGeometryTools.CalculateSharedArea(p1,p1),1e-12,"Test1 - Polygon1 in Polygon1");  
      Assert.AreEqual(p2.GetArea(),XYGeometryTools.CalculateSharedArea(p2,p2),1e-12,"Test2 - Polygon1 in Polygon1");  
      Assert.AreEqual(p4.GetArea(),XYGeometryTools.CalculateSharedArea(p4,p4),1e-12,"Test3 - Polygon1 in Polygon1");  
      Assert.AreEqual(p2.GetArea(),XYGeometryTools.CalculateSharedArea(p1,p2),1e-12,"Test4 - Polygon2 in Polygon1");  
      Assert.AreEqual(p1.GetArea(),XYGeometryTools.CalculateSharedArea(p1,p3),1e-12,"Test5 - Polygon1 in Polygon2");  
      Assert.AreEqual(4,XYGeometryTools.CalculateSharedArea(p1,p4),1e-12,"Test6 - Polygon1 in Polygon3");  
    }