Ejemplo n.º 1
0
        private void Initialize(double distance)
        {
            m_dDistance          = distance;
            maxCurveSegmentError = distance * (1 - Math.Cos(filletAngleQuantum / 2.0));

            ptList = new CoordinateCollection();
        }
Ejemplo n.º 2
0
        protected void AddPoints(Edge edge, bool isForward, bool isFirstEdge)
        {
            ICoordinateList edgePts = edge.Coordinates;

            if (isForward)
            {
                int startIndex = 1;
                if (isFirstEdge)
                {
                    startIndex = 0;
                }

                for (int i = startIndex; i < edgePts.Count; i++)
                {
                    pts.Add(edgePts[i]);
                }
            }
            else
            {
                // is backward
                int startIndex = edgePts.Count - 2;
                if (isFirstEdge)
                {
                    startIndex = edgePts.Count - 1;
                }

                for (int i = startIndex; i >= 0; i--)
                {
                    pts.Add(edgePts[i]);
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns true if the two arrays are identical, both null, or pointwise
        /// equal (as compared using <see cref="Coordinate.Equals"/>).
        /// </summary>
        /// <seealso cref="Coordinate.Equals">Coordinate.Equals</seealso>
        private static bool Equals(ICoordinateList coord1,
                                   ICoordinateList coord2)
        {
            if (coord1 == coord2)
            {
                return(true);
            }

            if (coord1 == null || coord2 == null)
            {
                return(false);
            }

            if (coord1.Count != coord2.Count)
            {
                return(false);
            }

            for (int i = 0; i < coord1.Count; i++)
            {
                if (!coord1[i].Equals(coord2[i]))
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 4
0
        private int depthDelta;         // the change in area depth from the R to L side of this edge

        #endregion

        #region Constructors and Destructor

        public Edge(ICoordinateList pts, Label label)
        {
            eiList          = new EdgeIntersectionList(this);
            depth           = new Depth();
            this.pts        = pts;
            this.m_objLabel = label;
        }
Ejemplo n.º 5
0
        private void ComputeLineBufferCurve(ICoordinateList inputPts)
        {
            int n = inputPts.Count - 1;

            // compute points for left side of line
            InitSideSegments(inputPts[0], inputPts[1], Position.Left);
            for (int i = 2; i <= n; i++)
            {
                AddNextSegment(inputPts[i], true);
            }
            AddLastSegment();
            // Add line cap for end of line
            AddLineEndCap(inputPts[n - 1], inputPts[n]);

            // compute points for right side of line
            InitSideSegments(inputPts[n], inputPts[n - 1], Position.Left);
            for (int i = n - 2; i >= 0; i--)
            {
                AddNextSegment(inputPts[i], true);
            }
            AddLastSegment();
            // Add line cap for start of line
            AddLineEndCap(inputPts[1], inputPts[0]);

            ClosePoints();
        }
Ejemplo n.º 6
0
        private void ComputeMinDistance(LineString line, Point pt,
                                        DistanceLocation[] locGeom)
        {
            if (line.Bounds.Distance(pt.Bounds) > minDistance)
            {
                return;
            }

            ICoordinateList coord0 = line.Coordinates;
            Coordinate      coord  = pt.Coordinate;

            // brute force approach!
            int nCount0 = coord0.Count;

            for (int i = 0; i < nCount0 - 1; i++)
            {
                double dist = CGAlgorithms.DistancePointLine(coord, coord0[i], coord0[i + 1]);
                if (dist < minDistance)
                {
                    minDistance = dist;
                    LineSegment seg =
                        new LineSegment(m_objFactory, coord0[i], coord0[i + 1]);
                    Coordinate segClosestPoint = seg.ClosestPoint(coord);
                    locGeom[0] = new DistanceLocation(line, i, segClosestPoint);
                    locGeom[1] = new DistanceLocation(pt, 0, coord);
                }

                if (minDistance <= terminateDistance)
                {
                    return;
                }
            }
        }
Ejemplo n.º 7
0
        private void AddLineString(LineString line)
        {
            ICoordinateList coord = CoordinateCollection.RemoveRepeatedCoordinates(line.Coordinates);

            if (coord.Count < 2)
            {
                m_bHasTooFewPoints = true;
                invalidPoint       = coord[0];
                return;
            }

            // Add the edge for the LineString
            // line edges do not have locations for their left and right sides
            Edge e = new Edge(coord, new Label(argIndex, LocationType.Interior));

//			object tempObject;
//			tempObject = e;
            lineEdgeMap[line] = e;
//			lineEdgeMap[line] = tempObject;
//			object generatedAux = tempObject;

            InsertEdge(e);

            // Add the boundary points of the LineString, if any.
            // Even if the LineString is closed, Add both points as if they were endpoints.
            // This allows for the case that the node already exists and is a boundary point.
            Debug.Assert(coord.Count >= 2, "found LineString with single point");
            InsertBoundaryPoint(argIndex, coord[0]);
            InsertBoundaryPoint(argIndex, coord[coord.Count - 1]);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Calculates the signed area for a ring.
        /// </summary>
        /// <remarks>
        /// Note that the sign of the returned area can be determined using
        /// the <see cref="Math.Sign"/> method.
        /// </remarks>
        /// <param name="ring">
        /// The array of coordinates of the points defining the ring.
        /// </param>
        /// <returns>
        /// The signed area for a ring. The area is positive if the ring
        /// is oriented clockwise.
        /// </returns>
        public static double SignedArea(ICoordinateList ring)
        {
            if (ring == null)
            {
                throw new ArgumentNullException("ring");
            }

            int nCount = ring.Count;

            if (nCount < 3)
            {
                return(0.0);
            }

            double sum = 0.0;

            for (int i = 0; i < nCount - 1; i++)
            {
                double bx = ring[i].X;
                double by = ring[i].Y;
                double cx = ring[i + 1].X;
                double cy = ring[i + 1].Y;
                sum += (bx + cx) * (cy - by);
            }

            return((-sum) / 2.0);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// This method handles single points as well as lines. Lines are assumed
        /// to not be closed (the function will not fail for closed lines, but
        /// will generate superfluous line caps).
        /// </summary>
        /// <returns>A List of <see cref="ICoordinateList"/>.</returns>
        public IList GetLineCurve(ICoordinateList inputPts, double distance)
        {
            ArrayList lineList = new ArrayList();

            // a zero or negative width Buffer of a line/point is empty
            if (distance <= 0.0)
            {
                return(lineList);
            }

            Initialize(distance);
            if (inputPts.Count <= 1)
            {
                switch (endCapStyle)
                {
                case BufferCapType.Round:
                    AddCircle(inputPts[0], distance);
                    break;

                case BufferCapType.Square:
                    AddSquare(inputPts[0], distance);
                    break;
                    // default is for Buffer to be empty (e.g. for a butt line cap);
                }
            }
            else
            {
                ComputeLineBufferCurve(inputPts);
            }

            lineList.Add(this.Coordinates);

            return(lineList);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Generates the WKT for a N-point <see cref="LineString"/>.
        /// </summary>
        /// <param name="seq">The sequence to outpout</param>
        /// <returns>
        /// A string containing the WKT of the LineString.
        /// </returns>
        public static string ToLineString(ICoordinateList seq)
        {
            StringBuilder buf = new StringBuilder();

            buf.Append("LINESTRING ");

            if (seq == null || seq.Count == 0)
            {
                buf.Append(" EMPTY");
            }
            else
            {
                buf.Append(WktLParan);

                int nCount = seq.Count;

                for (int i = 0; i < nCount; i++)
                {
                    if (i > 0)
                    {
                        buf.Append(WktComma);
                    }

                    Coordinate coord = seq[i];

                    buf.Append(coord.X + " " + coord.Y);
                }

                buf.Append(WktRParan);
            }

            return(buf.ToString());
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Converts the List of Coordinates to WKT format and appends it to output stream.
        /// </summary>
        /// <param name="coordinates">The list of coordinates to be converted.</param>
        /// <param name="writer">The output stream.</param>
        /// <param name="wrap">bool value indicating whether the list of coordinates should be enclosed in parathenes.</param>
        private static void AppendCoordinates(ICoordinateList coordinates, TextWriter writer, bool wrap)
        {
            if (coordinates.Count == 0)
            {
                return;
            }

            if (wrap)
            {
                writer.Write("(");
            }

            WktWriter.AppendCoordinate(coordinates[0], writer);

            for (int i = 1; i < coordinates.Count; i++)
            {
                writer.Write(", ");
                WktWriter.AppendCoordinate(coordinates[i], writer);
            }

            if (wrap)
            {
                writer.Write(")");
            }
        }
Ejemplo n.º 12
0
        private void  FindRightmostEdgeAtVertex()
        {
            /// <summary> The rightmost point is an interior vertex, so it has a segment on either side of it.
            /// If these segments are both above or below the rightmost point, we need to
            /// determine their relative orientation to decide which is rightmost.
            /// </summary>
            ICoordinateList pts = minDe.Edge.Coordinates;

            Debug.Assert(minIndex > 0 && minIndex < pts.Count, "rightmost point expected to be interior vertex of edge");
            Coordinate      pPrev       = pts[minIndex - 1];
            Coordinate      pNext       = pts[minIndex + 1];
            OrientationType orientation = CGAlgorithms.ComputeOrientation(minCoord, pNext, pPrev);
            bool            usePrev     = false;

            // both segments are below min point
            if (pPrev.Y < minCoord.Y && pNext.Y < minCoord.Y &&
                orientation == OrientationType.CounterClockwise)
            {
                usePrev = true;
            }
            else if (pPrev.Y > minCoord.Y && pNext.Y > minCoord.Y &&
                     orientation == OrientationType.Clockwise)
            {
                usePrev = true;
            }
            // if both segments are on the same side, do nothing - either is safe
            // to select as a rightmost segment
            if (usePrev)
            {
                minIndex = minIndex - 1;
            }
        }
Ejemplo n.º 13
0
        private int FindMaxPerpDistance(ICoordinateList pts, LineSegment seg, int startIndex)
        {
            double maxPerpDistance  = seg.DistancePerpendicular(pts[startIndex]);
            double nextPerpDistance = maxPerpDistance;
            int    maxIndex         = startIndex;
            int    NextIndex        = maxIndex;

            while (nextPerpDistance >= maxPerpDistance)
            {
                maxPerpDistance = nextPerpDistance;
                maxIndex        = NextIndex;

                NextIndex        = MinimumDiameter.NextIndex(pts, maxIndex);
                nextPerpDistance = seg.DistancePerpendicular(pts[NextIndex]);
            }
            // found maximum width for this segment - update global min dist if appropriate
            if (maxPerpDistance < minWidth)
            {
                minPtIndex = maxIndex;
                minWidth   = maxPerpDistance;
                minWidthPt = pts[minPtIndex];
                minBaseSeg = new LineSegment(seg, seg.Factory);
            }

            return(maxIndex);
        }
Ejemplo n.º 14
0
 private void AddInterior(ICoordinateList pts)
 {
     for (int i = 1; i < pts.Count - 1; i++)
     {
         Add(pts[i]);
     }
 }
Ejemplo n.º 15
0
        /// <summary>
        /// The left and right topological location arguments assume that the ring is oriented CW.
        /// If the ring is in the opposite orientation,
        /// the left and right locations must be interchanged.
        /// </summary>
        private void  AddPolygonRing(LinearRing lr, int cwLeft, int cwRight)
        {
            ICoordinateList coord = CoordinateCollection.RemoveRepeatedCoordinates(lr.Coordinates);

            if (coord.Count < 4)
            {
                m_bHasTooFewPoints = true;
                invalidPoint       = coord[0];
                return;
            }

            int left  = cwLeft;
            int right = cwRight;

            if (CGAlgorithms.IsCCW(coord))
            {
                left  = cwRight;
                right = cwLeft;
            }
            Edge e = new Edge(coord, new Label(argIndex, LocationType.Boundary, left, right));

//			object tempObject;
//			tempObject = e;
//			lineEdgeMap[lr] = tempObject;
//			object generatedAux = tempObject;
            lineEdgeMap[lr] = e;

            InsertEdge(e);
            // insert the endpoint as a node, to mark that it is on the boundary
            InsertPoint(argIndex, coord[0], LocationType.Boundary);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// This routine checks to see if a shell is properly contained in a hole.
        /// It assumes that the edges of the shell and hole do not
        /// properly intersect.
        /// </summary>
        /// <param name="shell"></param>
        /// <param name="hole"></param>
        /// <param name="graph"></param>
        /// <returns>
        /// null if the shell is properly contained, or a Coordinate which
        /// is not inside the hole if it is not
        /// </returns>
        private Coordinate CheckShellInsideHole(LinearRing shell, LinearRing hole, GeometryGraph graph)
        {
            ICoordinateList shellPts = shell.Coordinates;
            ICoordinateList holePts  = hole.Coordinates;
            // TODO: improve performance of this - by sorting pointlists for instance?
            Coordinate shellPt = FindPointNotNode(shellPts, hole, graph);

            // if point is on shell but not hole, check that the shell is inside the hole
            if (shellPt != null)
            {
                bool insideHole = CGAlgorithms.IsPointInRing(shellPt, holePts);
                if (!insideHole)
                {
                    return(shellPt);
                }
            }

            Coordinate holePt = FindPointNotNode(holePts, shell, graph);

            // if point is on hole but not shell, check that the hole is outside the shell
            if (holePt != null)
            {
                bool insideShell = CGAlgorithms.IsPointInRing(holePt, shellPts);
                if (insideShell)
                {
                    return(holePt);
                }

                return(null);
            }

            Debug.Assert(false, "Should never reach here: points in shell and hole appear to be equal");

            return(null);
        }
Ejemplo n.º 17
0
        private Stack GrahamScan(ICoordinateList c)
        {
            Coordinate p;
            Stack      ps = new Stack();

            ps.Push(c[0]);
            ps.Push(c[1]);
            ps.Push(c[2]);

            for (int i = 3; i < c.Count; i++)
            {
                p = (Coordinate)ps.Pop();
                while (CGAlgorithms.ComputeOrientation(
                           (Coordinate)ps.Peek(), p, c[i]) > 0)
                {
                    p = (Coordinate)ps.Pop();
                }
                ps.Push(p);
                ps.Push(c[i]);
                p = c[i];
            }

            ps.Push(c[0]);

            return(ps);
        }
Ejemplo n.º 18
0
        /// <param name="original"> the vertices of a linear ring, which may or may not be
        /// flattened (i.e. vertices collinear)
        /// </param>
        /// <returns>           the coordinates with unnecessary (collinear) vertices
        /// removed
        /// </returns>
        private ICoordinateList CleanRing(ICoordinateList original)
        {
            CoordinateCollection cleanedRing = new CoordinateCollection();
            Coordinate           previousDistinctCoordinate = null;

            for (int i = 0; i <= original.Count - 2; i++)
            {
                Coordinate currentCoordinate = original[i];
                Coordinate nextCoordinate    = original[i + 1];
                if (currentCoordinate.Equals(nextCoordinate))
                {
                    continue;
                }

                if (previousDistinctCoordinate != null && IsBetween(previousDistinctCoordinate, currentCoordinate, nextCoordinate))
                {
                    continue;
                }

                cleanedRing.Add(currentCoordinate);
                previousDistinctCoordinate = currentCoordinate;
            }

            cleanedRing.Add(original[original.Count - 1]);

            return(cleanedRing);
        }
Ejemplo n.º 19
0
//		private ICoordinateList ReduceQuad(ICoordinateList pts)
//		{
//			ConvexHull.BigQuad bigQuad = this.GetBigQuad(pts);
//
//			// Build a linear ring defining a big poly.
//			CoordinateCollection bigPoly = new CoordinateCollection();
//
//            bigPoly.Add(bigQuad.westmost);
//			if (!bigPoly.Contains(bigQuad.northmost))
//			{
//				bigPoly.Add(bigQuad.northmost);
//			}
//			if (!bigPoly.Contains(bigQuad.eastmost))
//			{
//				bigPoly.Add(bigQuad.eastmost);
//			}
//			if (!bigPoly.Contains(bigQuad.southmost))
//			{
//				bigPoly.Add(bigQuad.southmost);
//			}
//
//            if (bigPoly.Count < 3)
//			{
//				return pts;
//			}
//
//            bigPoly.Add(bigQuad.westmost);
//
//			LinearRing bQ = m_objFactory.CreateLinearRing(bigPoly);
//
//			// load an array with all points not in the big poly
//			// and the defining points.
//			CoordinateCollection reducedSet = new CoordinateCollection(bigPoly);
//			for (int i = 0; i < pts.Count; i++)
//			{
//				if (pointLocator.Locate(pts[i], bQ) == LocationType.Exterior)
//				{
//					reducedSet.Add(pts[i]);
//				}
//			}
//
//			// Return this array as the reduced problem.
//			return reducedSet;
//		}

        private ICoordinateList PreSort(ICoordinateList pts)
        {
            Coordinate t;

            // find the lowest point in the set. If two or more points have
            // the same minimum y coordinate choose the one with the minimu x.
            // This focal point is put in array location pts[0].
            for (int i = 1; i < pts.Count; i++)
            {
                if ((pts[i].Y < pts[0].Y) ||
                    ((pts[i].Y == pts[0].Y) && (pts[i].X < pts[0].X)))
                {
                    t      = pts[0];
                    pts[0] = pts[i];
                    pts[i] = t;
                }
            }

            // sort the points radially around the focal point.
            CoordinateCollection coordPts = (CoordinateCollection)pts;

            coordPts.Sort(1, coordPts.Count - 1, new RadialComparator(coordPts[0]));

            // sort the points radially around the focal point.
            //RadialSort(pts);

            return(pts);
        }
Ejemplo n.º 20
0
        protected override Envelope ComputeEnvelope()
        {
            if (IsEmpty)
            {
                return(new Envelope());
            }
            //Convert to array, then access array directly, to avoid the function-call overhead
            //of calling #get millions of times. #toArray may be inefficient for
            //non-BasicCoordinateSequence CoordinateSequences. [Jon Aquino]
            ICoordinateList coordinates = points;
            double          minx        = coordinates[0].X;
            double          miny        = coordinates[0].Y;
            double          maxx        = coordinates[0].X;
            double          maxy        = coordinates[0].Y;

            //OptimizeIt shows that Math#min and Math#max here are a bottleneck.
            //Replace with direct comparisons. [Jon Aquino]
            for (int i = 1; i < coordinates.Count; i++)
            {
                minx = minx < coordinates[i].X ? minx:coordinates[i].X;
                maxx = maxx > coordinates[i].X ? maxx:coordinates[i].X;
                miny = miny < coordinates[i].Y ? miny:coordinates[i].Y;
                maxy = maxy > coordinates[i].Y ? maxy:coordinates[i].Y;
            }
            return(new Envelope(minx, maxx, miny, maxy));
        }
Ejemplo n.º 21
0
        public Triangle(Coordinate p0, Coordinate p1,
                        Coordinate p2, GeometryFactory factory) : base(factory)
        {
            if (p0 == null)
            {
                throw new ArgumentNullException("p0");
            }
            if (p1 == null)
            {
                throw new ArgumentNullException("p1");
            }
            if (p2 == null)
            {
                throw new ArgumentNullException("p2");
            }

            m_objPoint1 = p0;
            m_objPoint2 = p1;
            m_objPoint3 = p2;

            m_objCoordinates = new CoordinateCollection();
            m_objCoordinates.Add(p0);
            m_objCoordinates.Add(p1);
            m_objCoordinates.Add(p2);
        }
Ejemplo n.º 22
0
        private void Normalize(LinearRing ring, bool clockwise)
        {
            if (ring.IsEmpty)
            {
                return;
            }

            CoordinateCollection uniqueCoordinates = new CoordinateCollection();

            for (int i = 0; i < ring.NumPoints - 1; i++)
            {
                uniqueCoordinates.Add(ring.GetCoordinate(i));           // copy all but last one into uniquecoordinates
            }

            Coordinate minCoordinate = CoordinateCollection.MinimumCoordinate(ring.Coordinates);

            uniqueCoordinates.Scroll(minCoordinate);

            ICoordinateList ringCoordinates = ring.Coordinates;

            ringCoordinates.Clear();
            ringCoordinates.AddRange(uniqueCoordinates);
            ringCoordinates.Add(uniqueCoordinates[0].Clone());          // add back in the closing point.

            if (CGAlgorithms.IsCCW(ringCoordinates) == clockwise)
            {
                ringCoordinates.Reverse();
            }
        }
Ejemplo n.º 23
0
        /// <summary>
        /// This algorithm does not attempt to first check the point against the envelope
        /// of the ring.
        ///
        /// </summary>
        /// <param name="ring">assumed to have first point identical to last point
        /// </param>
        public bool IsPointInRing(Coordinate p, ICoordinateList ring)
        {
            if (p == null)
            {
                throw new ArgumentNullException("p");
            }
            if (ring == null)
            {
                throw new ArgumentNullException("ring");
            }

            /*
             *  For each segment l = (i-1, i), see if it crosses ray from test point in positive x direction.
             */
            int crossings = 0;  // number of segment/ray crossings
            int nCount    = ring.Count;

            for (int i = 1; i < nCount; i++)
            {
                int        i1 = i - 1;
                Coordinate p1 = ring[i];
                Coordinate p2 = ring[i1];

                if (((p1.Y > p.Y) && (p2.Y <= p.Y)) ||
                    ((p2.Y > p.Y) && (p1.Y <= p.Y)))
                {
                    double x1 = p1.X - p.X;
                    double y1 = p1.Y - p.Y;
                    double x2 = p2.X - p.X;
                    double y2 = p2.Y - p.Y;

                    /*
                     *  segment straddles x axis, so compute intersection with x-axis.
                     */
                    double xInt = RobustDeterminant.SignOfDeterminant(x1, y1, x2, y2) / (y2 - y1);
                    //xsave = xInt;

                    /*
                     *  crosses ray if strictly positive intersection.
                     */
                    if (xInt > 0.0)
                    {
                        crossings++;
                    }
                }
            }

            /*
             *  p is inside if number of crossings is odd.
             */
            if ((crossings % 2) == 1)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Ejemplo n.º 24
0
        private int id;         // useful for optimizing chain comparisons

        #endregion

        #region Constructors and Destructor

        public MonotoneChain(ICoordinateList pts, int start,
                             int end, object context)
        {
            this.pts     = pts;
            this.start   = start;
            this.end     = end;
            this.context = context;
        }
Ejemplo n.º 25
0
 private void AddCurves(IList lineList, int leftLoc, int rightLoc)
 {
     for (IEnumerator i = lineList.GetEnumerator(); i.MoveNext();)
     {
         ICoordinateList coords = (ICoordinateList)i.Current;
         AddCurve(coords, leftLoc, rightLoc);
     }
 }
Ejemplo n.º 26
0
 private void CompareCoordinateLists(ICoordinateList list, ICoordinateList expected)
 {
     Assert.Equal(expected.Count, list.Count);
     for (int i = 0; i < expected.Count; i++)
     {
         Assert.Equal(expected[i], list[i]);
     }
 }
Ejemplo n.º 27
0
        public SimplePointInRing(LinearRing ring)
        {
            if (ring == null)
            {
                throw new ArgumentNullException("ring");
            }

            pts = ring.Coordinates;
        }
Ejemplo n.º 28
0
        private void CompareCoordinates(Coordinate[] expected, ICoordinateList actual)
        {
            Assert.Equal(expected.Length, actual.Count);

            for (int i = 0; i < expected.Length; i++)
            {
                Assert.Equal(expected[i], actual[i]);
            }
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Writes list of Coordinates to the output using specified writer.
        /// </summary>
        /// <param name="coordinates">The list od Coordinates to write.</param>
        /// <param name="writer">The BinaryWriter used to write geometry to the output.</param>
        private static void WriteCoordinates(ICoordinateList coordinates, BinaryWriter writer)
        {
            writer.Write((uint)coordinates.Count);

            for (int i = 0; i < coordinates.Count; i++)
            {
                WkbWriter.WriteCoordinate(coordinates[i], writer);
            }
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Assumes input is valid (e.g. start &lt;= end)
        /// </summary>
        /// <param name="start">
        /// </param>
        /// <param name="end">
        /// </param>
        /// <returns>A linear geometry.</returns>
        private LineString ComputeLine(LinearLocation start, LinearLocation end)
        {
            ICoordinateList      coordinates    = line.Coordinates;
            CoordinateCollection newCoordinates = new CoordinateCollection();

            int startSegmentIndex = start.SegmentIndex;

            if (start.SegmentFraction > 0.0)
            {
                startSegmentIndex += 1;
            }
            int lastSegmentIndex = end.SegmentIndex;

            if (end.SegmentFraction == 1.0)
            {
                lastSegmentIndex += 1;
            }
            if (lastSegmentIndex >= coordinates.Count)
            {
                lastSegmentIndex = coordinates.Count - 1;
            }
            // not needed - LinearLocation values should always be correct
            //Assert.isTrue(end.getSegmentFraction() <= 1.0, "invalid segment fraction value");

            if (!start.Vertex)
            {
                newCoordinates.Add(start.GetCoordinate(line));
            }

            for (int i = startSegmentIndex; i <= lastSegmentIndex; i++)
            {
                newCoordinates.Add(coordinates[i]);
            }
            if (!end.Vertex)
            {
                newCoordinates.Add(end.GetCoordinate(line));
            }

            // ensure there is at least one coordinate in the result
            if (newCoordinates.Count <= 0)
            {
                newCoordinates.Add(start.GetCoordinate(line));
            }

            Coordinate[] newCoordinateArray = newCoordinates.ToArray();

            // Ensure there is enough coordinates to build a valid line.
            // Make a 2-point line with duplicate coordinates, if necessary.
            // There will always be at least one coordinate in the coordList.
            if (newCoordinateArray.Length <= 1)
            {
                newCoordinateArray = new Coordinate[] { newCoordinateArray[0],
                                                        newCoordinateArray[0] };
            }

            return(line.Factory.CreateLineString(newCoordinateArray));
        }
Ejemplo n.º 31
0
        /// <summary>
        /// Determines whether two polylines defined by series of coordinates intersects
        /// </summary>
        /// <param name="line1">The first polyline to test</param>
        /// <param name="line2">The second polyline to test</param>
        /// <returns>true if polylines intersets, otherwise false</returns>
        public bool Intersects(ICoordinateList line1, ICoordinateList line2)
        {
            //TODO implement more efficient algorithm

            for (int i = 1; i < line1.Count; i++) {
                for (int ii = 1; ii < line2.Count; ii++) {
                    if (this.Intersects(line1[i - 1], line1[i], LineMode.LineSegment, line2[ii - 1], line2[ii], LineMode.LineSegment)) {
                        return true;
                    }
                }
            }

            return false;
        }
Ejemplo n.º 32
0
        /// <summary>
        /// Calculates area of the polygon specified by given vertices
        /// </summary>
        /// <param name="vertices">The vertices of the polygon</param>
        /// <returns>The area of the polygon in squareed coordinate's units</returns>
        /// <remarks>Polygon is expected to be simple. ComputeArea method handles correctly CoordinateList from Polygon class, where first and last vertices are the same.</remarks>
        public double CalculateArea(ICoordinateList vertices)
        {
            if (vertices.Count < 3) {
                throw new ArgumentException("List must contain at least 3 vertices.", "vertices");
            }

            double area = 0;
            int maxIndex = vertices.Count - 1;
            if (vertices[0] != vertices[maxIndex]) {
                maxIndex++;
            }

            for (int i = 0; i < maxIndex; i++) {
                area += (vertices[(i + 1) % vertices.Count].X + vertices[i % vertices.Count].X) * (vertices[(i + 1) % vertices.Count].Y - vertices[i % vertices.Count].Y);
            }

            return area / 2.0;
        }
Ejemplo n.º 33
0
        /// <summary>
        /// Calculates area of the polygon on the surface of a sphere specified by given vertices.
        /// </summary>
        /// <param name="vertices">The vertices of the polygon.</param>
        /// <returns>The area of the polygon in squared units of the <see cref="Sphere2DCalculator.Radius"/> property.</returns>
        /// <remarks>Polygon is expected to be simple.</remarks>
        public double CalculateArea(ICoordinateList vertices)
        {
            if (vertices.Count < 3) {
                throw new ArgumentException("List must contain at least 3 vertices.", "vertices");
            }

            double area = 0;
            int maxIndex = vertices.Count - 1;
            if (vertices[0] != vertices[maxIndex]) {
                maxIndex++;
            }

            for (int i = 0; i <= maxIndex; i++) {
                area += (this.ToRadians(vertices[(i + 1) % maxIndex].X) - this.ToRadians(vertices[(i - 1) % maxIndex].X)) * Math.Sin(this.ToRadians(vertices[i % maxIndex].Y));
            }

            return Math.Abs(area * Sphere2DCalculator.EarthRadius * Sphere2DCalculator.EarthRadius);
        }
Ejemplo n.º 34
0
        /// <summary>
        /// Determines if specific point is in ring
        /// </summary>
        /// <param name="c">The coordinate to be tested</param>
        /// <param name="ring">The ring to locate point in</param>
        /// <returns>True if point lies inside ring, otherwise false</returns>
        public bool IsInRing(Coordinate c, ICoordinateList ring)
        {
            if (ring.Count < 3) {
                throw new ArgumentException("Ring must contain at least 3 points", "ring");
            }

            if (ring[0].Equals2D(ring[ring.Count - 1]) == false) {
                throw new ArgumentException("Ring does not have the same endpoints", "ring");
            }

            // determine if point is in ring using ray-tracing algorithm
            // ray is casted from c in the direction of positive x-axis
            int crossings = 0;

            for (int i = 0; i < ring.Count; i++) {
                Coordinate p1 = ring[i];
                Coordinate p2 = ring[(i + 1) % ring.Count];

                double y1 = p1.Y - c.Y;
                double y2 = p2.Y - c.Y;

                // check there can be crossing - c lies between P1 and P2 on y-axis
                if (((y1 > 0) && (y2 <= 0)) || ((y2 > 0) && (y1 <= 0))) {
                    double x1 = p1.X - c.X;
                    double x2 = p2.X - c.X;

                    // compute intersection
                    double intersection = (x1 * y2 - x2 * y1) / (y2 - y1);

                    if (intersection > 0) {
                        crossings++;
                    }
                }
            }

            // p is inside if an odd number of crossings
            if ((crossings % 2) == 1) {
                return true;
            }
            else {
                return false;
            }
        }
Ejemplo n.º 35
0
        /// <summary>
        /// Determines whether specific coordinate is on the given polyline
        /// </summary>
        /// <param name="c">The coordinate to be tested</param>
        /// <param name="line">The polyline</param>
        /// <returns>true if coordinate C is on the line, otherwise false</returns>
        public bool IsOnLine(Coordinate c, ICoordinateList line)
        {
            for (int i = 1; i < line.Count; i++) {
                if (this.IsOnLine(c, line[i - 1], line[i], LineMode.LineSegment)) {
                    return true;
                }
            }

            return false;
        }
Ejemplo n.º 36
0
        private void CompareCoordinates(Coordinate[] expected, ICoordinateList actual)
        {
            Assert.Equal(expected.Length, actual.Count);

            for (int i = 0; i < expected.Length; i++) {
                Assert.Equal(expected[i], actual[i]);
            }
        }
Ejemplo n.º 37
0
        /// <summary>
        /// Writes list of Coordinates to the output using specified writer.
        /// </summary>
        /// <param name="coordinates">The list od Coordinates to write.</param>
        /// <param name="writer">The BinaryWriter used to write geometry to the output.</param>
        private static void WriteCoordinates(ICoordinateList coordinates, BinaryWriter writer)
        {
            writer.Write((uint)coordinates.Count);

            for (int i = 0; i < coordinates.Count; i++) {
                WkbWriter.WriteCoordinate(coordinates[i], writer);
            }
        }
Ejemplo n.º 38
0
 /// <summary>
 /// Initializes a new instance of the <c>Polygon</c> class with the given exterior boundary in WSG84 coordinate reference system.
 /// </summary>
 /// <param name="exteriorRing">The exterior boundary of the polygon.</param>
 public Polygon(ICoordinateList exteriorRing)
 {
     this.ExteriorRing = exteriorRing;
     this.InteriorRings = new List<ICoordinateList>(0);
 }
Ejemplo n.º 39
0
        /// <summary>
        /// Converts the List of Coordinates to WKT format and appends it to output stream.
        /// </summary>
        /// <param name="coordinates">The list of coordinates to be converted.</param>
        /// <param name="writer">The output stream.</param>
        /// <param name="wrap">bool value indicating whether the list of coordinates should be enclosed in parathenes.</param>
        private static void AppendCoordinates(ICoordinateList coordinates, TextWriter writer, bool wrap)
        {
            if (coordinates.Count == 0) {
                return;
            }

            if (wrap) {
                writer.Write("(");
            }

            WktWriter.AppendCoordinate(coordinates[0], writer);

            for (int i = 1; i < coordinates.Count; i++) {
                writer.Write(", ");
                WktWriter.AppendCoordinate(coordinates[i], writer);
            }

            if (wrap) {
                writer.Write(")");
            }
        }
Ejemplo n.º 40
0
 private void CompareCoordinateLists(ICoordinateList list, ICoordinateList expected)
 {
     Assert.Equal(expected.Count, list.Count);
     for (int i = 0; i < expected.Count; i++) {
         Assert.Equal(expected[i], list[i]);
     }
 }