예제 #1
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="linearRing"></param>
 /// <param name="writer"></param>
 protected virtual void Write(LinearRing linearRing, XmlTextWriter writer)
 {
     writer.WriteStartElement("LinearRing");
     Write(linearRing.Coordinates, writer);
     writer.WriteEndElement();
 }
예제 #2
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="reader"></param>
 /// <returns></returns>
 protected virtual IGeometry ReadPolygon(BinaryReader reader)
 {
     int numRings = reader.ReadInt32();
     ILinearRing exteriorRing = ReadRing(reader);
     ILinearRing[] interiorRings = new LinearRing[numRings - 1];
     for (int i = 0; i < numRings - 1; i++)
         interiorRings[i] = ReadRing(reader);
     return Factory.CreatePolygon(exteriorRing, interiorRings);
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ring"></param>
 public virtual void Add(LinearRing ring)
 {
     _rings.Add(ring);
     _totalEnv.ExpandToInclude(ring.EnvelopeInternal);
 }
예제 #4
0
        /// <summary>
        /// If the FeatureType is polygon, this is the code for converting the vertex array
        /// into a feature.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected IFeature GetPolygon(int index)
        {
            Feature feature = new Feature();
            feature.Envelope = ShapeIndices[index].Extent.ToEnvelope();
            ShapeRange shape = ShapeIndices[index];
            List<ILinearRing> shells = new List<ILinearRing>();
            List<ILinearRing> holes = new List<ILinearRing>();
            foreach (PartRange part in shape.Parts)
            {
                List<Coordinate> coords = new List<Coordinate>();
                int i = part.StartIndex;
                foreach (Vertex d in part)
                {
                    Coordinate c = new Coordinate(d);
                    if (M != null && M.Length > 0) c.M = M[i];
                    if (Z != null && Z.Length > 0) c.Z = Z[i];
                    i++;
                    coords.Add(c);
                }
                LinearRing ring = new LinearRing(coords);
                if (shape.Parts.Count == 1)
                {
                    shells.Add(ring);
                }
                else
                {
                    if (CGAlgorithms.IsCounterClockwise(ring.Coordinates))
                    {
                        holes.Add(ring);
                    }
                    else
                    {
                        shells.Add(ring);
                    }
                    //if(part.IsHole())
                    //{
                    //    holes.Add(ring);
                    //}
                    //else
                    //{
                    //    shells.Add(ring);
                    //}
                }
            }
            //// Now we have a list of all shells and all holes
            List<ILinearRing>[] holesForShells = new List<ILinearRing>[shells.Count];
            for (int i = 0; i < shells.Count; i++)
            {
                holesForShells[i] = new List<ILinearRing>();
            }

            // Find holes
            for (int i = 0; i < holes.Count; i++)
            {
                ILinearRing testRing = holes[i];
                ILinearRing minShell = null;
                IEnvelope minEnv = null;
                IEnvelope testEnv = testRing.EnvelopeInternal;
                Coordinate testPt = testRing.Coordinates[0];
                ILinearRing tryRing;
                for (int j = 0; j < shells.Count; j++)
                {
                    tryRing = shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                        minEnv = minShell.EnvelopeInternal;
                    bool isContained = false;

                    if (tryEnv.Contains(testEnv)
                        && (CGAlgorithms.IsPointInRing(testPt, tryRing.Coordinates)
                        || (PointInList(testPt, tryRing.Coordinates))))
                    {
                        isContained = true;
                    }

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        if (minShell == null || minEnv.Contains(tryEnv))
                        {
                            minShell = tryRing;
                        }
                        holesForShells[j].Add(holes[i]);
                    }
                }
            }

            IPolygon[] polygons = new Polygon[shells.Count];
            for (int i = 0; i < shells.Count; i++)
            {
                polygons[i] = new Polygon(shells[i], holesForShells[i].ToArray());
            }

            if (polygons.Length == 1)
            {
                feature.BasicGeometry = polygons[0];
            }
            else
            {
                // It's a multi part
                feature.BasicGeometry = new MultiPolygon(polygons);
            }
            // feature.FID = feature.RecordNumber; FID is now dynamic
            feature.ParentFeatureSet = this;
            feature.ShapeIndex = shape;
            feature.RecordNumber = shape.RecordNumber;
            feature.ContentLength = shape.ContentLength;
            feature.ShapeType = shape.ShapeType;
            //Attributes handled in the overridden case
            return feature;
        }
예제 #5
0
        /// <summary>
        /// Check if a shell is incorrectly nested within a polygon.  This is the case
        /// if the shell is inside the polygon shell, but not inside a polygon hole.
        /// (If the shell is inside a polygon hole, the nesting is valid.)
        /// The algorithm used relies on the fact that the rings must be properly contained.
        /// E.g. they cannot partially overlap (this has been previously checked by
        /// <c>CheckRelateConsistency</c>).
        /// </summary>
        private void CheckShellNotNested(LinearRing shell, Polygon p, GeometryGraph graph)
        {
            IList<Coordinate> shellPts = shell.Coordinates;
            // test if shell is inside polygon shell
            LinearRing polyShell = (LinearRing)p.ExteriorRing;
            IList<Coordinate> polyPts = polyShell.Coordinates;
            Coordinate shellPt = FindPointNotNode(shellPts, polyShell, graph);
            // if no point could be found, we can assume that the shell is outside the polygon
            if (shellPt == null) return;
            bool insidePolyShell = CGAlgorithms.IsPointInRing(shellPt, polyPts);
            if (!insidePolyShell) return;
            // if no holes, this is an error!
            if (p.NumHoles <= 0)
            {
                _validErr = new TopologyValidationError(TopologyValidationErrors.NestedShells, shellPt);
                return;
            }

            /*
             * Check if the shell is inside one of the holes.
             * This is the case if one of the calls to checkShellInsideHole
             * returns a null coordinate.
             * Otherwise, the shell is not properly contained in a hole, which is an error.
             */
            Coordinate badNestedPt = null;
            for (int i = 0; i < p.NumHoles; i++)
            {
                LinearRing hole = (LinearRing)p.GetInteriorRingN(i);
                badNestedPt = CheckShellInsideHole(shell, hole, graph);
                if (badNestedPt == null) return;
            }
            _validErr = new TopologyValidationError(TopologyValidationErrors.NestedShells, badNestedPt);
        }
예제 #6
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>
 /// <c>null</c> if the shell is properly contained, or
 /// a Coordinate which is not inside the hole if it is not.
 /// </returns>
 private static Coordinate CheckShellInsideHole(LinearRing shell, LinearRing hole, GeometryGraph graph)
 {
     IList<Coordinate> shellPts = shell.Coordinates;
     IList<Coordinate> holePts = hole.Coordinates;
     // TODO: improve performance of this - by sorting pointlists?
     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;
     }
     Assert.ShouldNeverReachHere("points in shell and hole appear to be equal");
     return null;
 }
예제 #7
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="geometryFactory"></param>
 /// <returns></returns>
 public virtual IPolygon ToPolygon(IGeometryFactory geometryFactory)
 {
     ILinearRing[] holeLR = new LinearRing[_holes.Count];
     for (int i = 0; i < _holes.Count; i++)
         holeLR[i] = ((EdgeRing)_holes[i]).LinearRing;
     IPolygon poly = geometryFactory.CreatePolygon(LinearRing, holeLR);
     return poly;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ring"></param>
 public virtual void Add(LinearRing ring)
 {
     _rings.Add(ring);
 }
예제 #9
0
        /// <summary>
        /// Constructor for a polygon
        /// </summary>
        /// <param name="polygonBase">A simpler BasicPolygon to empower with topology functions</param>
        public Polygon(IBasicPolygon polygonBase)
            : base(DefaultFactory)
        {
            SetHoles(polygonBase.Holes);
            
            LinearRing shell = new LinearRing(polygonBase.Shell);
            if (HasNullElements(_holes))
                throw new PolygonException(MessageStrings.PolygonException_HoleElementNull);
            if (shell.IsEmpty && HasNonEmptyElements(_holes))
                throw new PolygonException(MessageStrings.PolygonException_ShellEmptyButHolesNot);
            _shell = shell;


        }
예제 #10
0
 /// <summary>
 /// Constructs a <c>Polygon</c> with the given exterior boundary and
 /// interior boundaries.
 /// </summary>       
 /// <param name="inShell">
 /// The outer boundary of the new <c>Polygon</c>,
 /// or <c>null</c> or an empty <c>LinearRing</c> if the empty
 /// point is to be created.
 /// </param>
 /// <param name="inHoles">
 /// The inner boundaries of the new <c>Polygon</c>
 /// , or <c>null</c> or empty <c>LinearRing</c>s if the empty
 /// point is to be created.
 /// </param>
 /// <param name="factory"></param>
 /// <exception cref="PolygonException">Holes must not contain null elements</exception>
 public Polygon(ILinearRing inShell, ILinearRing[] inHoles, IGeometryFactory factory)
     : base(factory)
 {
     if (inShell == null)
         inShell = Factory.CreateLinearRing(null);
     if (inHoles == null)
         inHoles = new LinearRing[] { };
     if (HasNullElements(inHoles))
     {
         throw new PolygonException(MessageStrings.PolygonException_HoleElementNull);
     }
     if (inShell.IsEmpty && HasNonEmptyElements(inHoles))
         throw new PolygonException(MessageStrings.PolygonException_ShellEmptyButHolesNot);
     _shell = inShell;
     _holes = inHoles;
 }
        private int _crossings;  // number of segment/ray crossings

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ring"></param>
        public SIRtreePointInRing(LinearRing ring)
        {
            _ring = ring;
            BuildIndex();
        }