Ejemplo n.º 1
0
        /// <summary>
        /// Calculates the intersection of a polygon shape without relying on the NTS geometry
        /// </summary>
        /// <param name="polygonShape"></param>
        /// <param name="otherShape"></param>
        /// <returns></returns>
        public static bool Intersects(ShapeRange polygonShape, ShapeRange otherShape)
        {
            if (polygonShape.FeatureType != FeatureTypes.Polygon)
            {
                throw new ArgumentException("The First parameter should be a point shape, but it was featuretype:" + polygonShape.FeatureType);
            }

            // Extents will have already been tested by this point.
            // Regardless of what the other shapetype is, a coordinate inside this polygon indicates a hit.
            if (ContainsVertex(polygonShape, otherShape)) return true;

            // There is no other way for this polygon to intersect the other points
            if(otherShape.FeatureType == FeatureTypes.Point || otherShape.FeatureType ==FeatureTypes.MultiPoint)
                return false;

            // For lines and polygons, if any segment intersects any segment of this polygon shape, return true.
            // This is essentially looking for the rare case of crossing in and crossing out again with
            // no actual points inside this polygonShape.
            if (LineShape.SegmentsIntersect(polygonShape, otherShape)) return true;

            // There is no other way for this polygon to intersect the other lines
            if (otherShape.FeatureType == FeatureTypes.Line) return false;

            
            // If the other polygon completely contains this polygon every other test has returned false, 
            // but this will test for that case with only a single point.
            Vertex v = polygonShape.First();
            ShapeRange onlyFirstPoint = new ShapeRange(polygonShape.First());
            return ContainsVertex(otherShape, onlyFirstPoint);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Creates a shape based on the specified feature.  This shape will be standing alone,
 /// all by itself.  The fieldnames and field types will be null.
 /// </summary>
 /// <param name="feature"></param>
 public Shape(IFeature feature)
 {
     _shapeRange = new ShapeRange(feature.FeatureType);
     _attributes = feature.DataRow.ItemArray;
     IList<Coordinate> coords = feature.Coordinates;
     _vertices = new double[feature.NumPoints*2];
     _z = new double[feature.NumPoints];
     _m = new double[feature.NumPoints];
     for (int i = 0; i < coords.Count; i++)
     {
         Coordinate c = coords[i];
         _vertices[i*2] = c.X;
         _vertices[i*2 + 1] = c.Y;
         _z[i] = c.Z;
         _m[i] = c.M;
     }
     int offset = 0;
     for(int ig = 0; ig < feature.NumGeometries; ig++)
     {
         IBasicGeometry g = feature.GetBasicGeometryN(ig);
         PartRange prt = new PartRange(_vertices, 0, offset, feature.FeatureType);
         _shapeRange.Parts.Add(prt);
         offset += g.NumPoints;
     }
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Calculates the intersection of a polygon shape without relying on the NTS geometry
        /// </summary>
        /// <param name="lineShape"></param>
        /// <param name="otherShape"></param>
        /// <returns></returns>
        public static bool Intersects(ShapeRange lineShape, ShapeRange otherShape)
        {
            if (lineShape.FeatureType != FeatureTypes.Line)
            {
                throw new ArgumentException("The First parameter should be a point shape, but it was featuretype:" + lineShape.FeatureType);
            }

            // Implmented in PolygonShape
            if(otherShape.FeatureType == FeatureTypes.Polygon)
            {
                return otherShape.Intersects(lineShape);
            }

            // Test for point on a line
            if(otherShape.FeatureType == FeatureTypes.Point || otherShape.FeatureType == FeatureTypes.MultiPoint)
            {
                return IntersectsVertex(lineShape, otherShape);
            }
           

            // There is no other way for this polygon to intersect the other points
            if (otherShape.FeatureType == FeatureTypes.Point || otherShape.FeatureType == FeatureTypes.MultiPoint)
                return false;

            // For lines and polygons, if any segment intersects any segment of this polygon shape, return true.
            // This is essentially looking for the rare case of crossing in and crossing out again with
            // no actual points inside this polygonShape.
            return SegmentsIntersect(lineShape, otherShape);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Calculates the intersection of a polygon shape without relying on the NTS geometry
        /// </summary>
        /// <param name="pointShape"></param>
        /// <param name="otherShape"></param>
        /// <returns></returns>
        public static bool Intersects(ShapeRange pointShape, ShapeRange otherShape)
        {
            if(pointShape.FeatureType != FeatureTypes.Point && pointShape.FeatureType != FeatureTypes.MultiPoint)
            {
                throw new ArgumentException("The First parameter should be a point shape, but it was featuretype:" + pointShape.FeatureType);
            }

            // Implmented in PolygonShape or line shape.  Point shape is the simplest and just looks for overlapping coordinates.
            if (otherShape.FeatureType == FeatureTypes.Polygon || otherShape.FeatureType == FeatureTypes.Line)
            {
                return otherShape.Intersects(pointShape);
            }

            // For two point-type shapes, test if any vertex from one overlaps with any vertex of the other within Epsilon tollerance
            return VerticesIntersect(pointShape, otherShape);
            
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Returns true if any vertices overlap
 /// </summary>
 /// <returns></returns>
 public static bool VerticesIntersect(ShapeRange pointShape, ShapeRange otherPointShape)
 {
     foreach (PartRange part in pointShape.Parts)
     {
         foreach (PartRange oPart in otherPointShape.Parts)
         {
             foreach(Vertex v1 in part)
             {
                 foreach (Vertex v2 in oPart)
                 {
                     if(v1 == v2) return true;
                 }
             }
         }
     }
     return false;
 }
Ejemplo n.º 6
0
 /// <summary>
 /// Creates a new shape type where the shaperange exists and has a type specified
 /// </summary>
 /// <param name="type"></param>
 public Shape(FeatureTypes type)
 {
     _shapeRange = new ShapeRange(type);
 }
Ejemplo n.º 7
0
     private static void ReadMultiPolygon(Stream data, FeatureSetPack results)
     {
         int numPolygons = ReadInt32(data);
         ShapeRange lShp = new ShapeRange(FeatureTypes.Polygon);
         List<double[]> rings = new List<double[]>();
         int partOffset = 0;
         for (int iPoly = 0; iPoly < numPolygons; iPoly++ )
         {
             data.Seek(5, SeekOrigin.Current); // endian and geometry type
             int numRings = ReadInt32(data);
             for (int iRing = 0; iRing < numRings; iRing++)
             {
                 int numPoints = ReadInt32(data); // ring structures are like a linestring without the final point.
                 double[] coords = ReadDouble(data, 2 * numPoints);
                 if (iRing == 0)
                 {
                     // By shapefile standard, the shell should be clockwise
                     if (IsCounterClockwise(coords)) ReverseCoords(coords);
                 }
                 else
                 {
                     // By shapefile standard, the holes should be counter clockwise.
                     if (!IsCounterClockwise(coords)) ReverseCoords(coords);
                 }
                 PartRange lPrt = new PartRange(FeatureTypes.Polygon);
                 lPrt.PartOffset = partOffset;
                 lPrt.NumVertices = numPoints;
                 lShp.Parts.Add(lPrt);
                 partOffset += coords.Length / 2;
                 rings.Add(coords);
             }
         }
 
         double[] allVertices = new double[partOffset * 2];
         int offset = 0;
         foreach (double[] ring in rings)
         {
             Array.Copy(ring, 0, allVertices, offset, ring.Length);
             offset += ring.Length;
         }
         results.Add(allVertices, lShp);
     }
Ejemplo n.º 8
0
        /// <summary>
        /// For each coordinate in the other part, if it falls in the extent of this polygon, a 
        /// ray crossing test is used for point in polygon testing.  If it is not in the extent,
        /// it is skipped.
        /// </summary>
        /// <param name="polygonShape">The part of the polygon to analyze polygon</param>
        /// <param name="otherPart">The other part</param>
        /// polygonshape and the shape extent is the same as the part extent.</param>
        /// <returns>Boolean, true if any coordinate falls inside the polygon</returns>
        private static bool ContainsVertex(ShapeRange polygonShape, PartRange otherPart)
        {
            // Create an extent for faster checking in most cases
            Extent ext = polygonShape.Extent;

            foreach (Vertex point in otherPart)
            {
                // This extent check shortcut should help speed things up for large polygon parts
                if (!ext.Intersects(point)) continue;
                
                // Imagine a ray on the horizontal starting from point.X -> infinity.  (In practice this can be ext.XMax)
                // Count the intersections of segments with that line.  If the resulting count is odd, the point is inside.
                double x1 = point.X;
                double y1 = point.Y;
                double x2 = ext.XMax;
                Segment ray = new Segment(point.X, point.Y, ext.XMax, point.Y);
                int[] numCrosses = new int[polygonShape.NumParts]; // A cross is a complete cross.  Coincident doesn't count because it is either 0 or 2 crosses.
                int totalCrosses = 0;
                int iPart = 0;
                foreach (PartRange ring in polygonShape.Parts)
                {
                   
                    foreach (Segment segment in ring.Segments)
                    {
                        if(segment.IntersectionCount(ray) != 1) continue;
                        numCrosses[iPart]++;
                        totalCrosses++;
                    }
                    iPart++;
                }

                // If we didn't actually have any polygons we cant intersect with anything
                if (polygonShape.NumParts < 1) return false;

                // For shapes with only one part, we don't need to test part-containment.
                if(polygonShape.NumParts == 1 && totalCrosses % 2 == 1) return true;

                // Regardless of number of parts or holiness, 1 crossing can only be inside.
                if(totalCrosses == 1) return true;

                
                totalCrosses = 0;
                for (iPart = 0; iPart < numCrosses.Length; iPart++)
                {
                    int count = numCrosses[iPart];
                    // If this part does not contain the point, don't bother trying to figure out if the part is a hole or not.
                    if (count % 2 == 0) continue;
                    
                    // If this particular part is a hole, subtract the total crosses by 1,  otherwise add one.
                    // This takes time, so we want to do this as few times as possible.
                    if(polygonShape.Parts[iPart].IsHole())
                    {
                        totalCrosses--;
                    }
                    else
                    {
                        totalCrosses++;
                    }
                }
                return totalCrosses > 0;

            }
            return false;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// returns only the features that have envelopes that
        /// intersect with the specified envelope.  If in indexMode, this uses the ShapeIndices to create
        /// features on demand, rather than loading all the features.  It is much faster to use selectIndices
        /// when in index mode.
        /// </summary>
        /// <param name="region">The specified region to test for intersect with</param>
        /// <param name="affectedRegion">This returns the geographic extents that contains the modified contents.</param>
        /// <returns>A List of the IFeature elements that are contained in this region</returns>
        public virtual List<IFeature> Select(IEnvelope region, out IEnvelope affectedRegion)
        {
            List<IFeature> result = new List<IFeature>();
            if(IndexMode)
            {
                ShapeRange aoi = new ShapeRange(new Extent(region));
                IEnvelope env = region.Copy();
                Extent affected = new Extent();
                List<ShapeRange> shapes = ShapeIndices;
                if(shapes != null)
                {
                    for(int shp = 0; shp < shapes.Count; shp++)
                    {
                        if (!shapes[shp].Intersects(aoi)) continue;
                        IFeature f = GetFeature(shp);
                        affected.ExpandToInclude(shapes[shp].Extent);
                        result.Add(f);
                    }
                }
                affectedRegion = affected.ToEnvelope();
                return result;
            }

            affectedRegion = new Envelope();

            foreach (IFeature feature in Features)
            {
                if (!feature.Envelope.Intersects(region)) continue;
                result.Add(feature);
                affectedRegion.ExpandToInclude(feature.Envelope);
            }
            return result;

        }
Ejemplo n.º 10
0
        /// <summary>
        /// Obtains a typed list of ShapefilePoint structures with double values associated with the various coordinates.
        /// </summary>
        /// <param name="filename">A string filename</param>
        /// <param name="progressHandler">A progress indicator</param>
        private void FillPoints(string filename, IProgressHandler progressHandler)
        {
            

            // Check to ensure the filename is not null
            if (filename == null)
            {
                throw new NullReferenceException(MessageStrings.ArgumentNull_S.Replace("%S",filename));
            }

            if (File.Exists(filename) == false)
            {
                throw new FileNotFoundException(MessageStrings.FileNotFound_S.Replace("%S", filename));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(filename);

            // Get the basic header information.  
            ShapefileHeader header = new ShapefileHeader(filename);
            Extent = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });
            Envelope = Extent.ToEnvelope();
            // Check to ensure that the filename is the correct shape type
            if (header.ShapeType != ShapeTypes.Point && header.ShapeType != ShapeTypes.PointM && header.ShapeType != ShapeTypes.PointZ)
            {
                throw new ApplicationException(MessageStrings.FileNotPoints_S.Replace("%S", filename));
            }

            // This will set up a reader so that we can read values in huge chunks, which is much faster than one value at a time.
            IO.BufferedBinaryReader bbReader = new IO.BufferedBinaryReader(filename, progressHandler);

            if (bbReader.FileLength == 100)
            {
                bbReader.Close();
                // the file is empty so we are done reading
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);
            int numShapes = shapeHeaders.Count;
            byte[] bigEndian = new byte[numShapes * 8];
            byte[] allCoords = new byte[numShapes * 16];
            bool isM = false;
            bool isZ = false;
            if(header.ShapeType == ShapeTypes.PointM || header.ShapeType == ShapeTypes.PointZ)
            {
                isM = true;
            }
            if (header.ShapeType == ShapeTypes.PointZ)
            {
                isZ = true;
            }
            byte[] allM = new byte[8];
            if(isM) allM = new byte[numShapes * 8];
            byte[] allZ = new byte[8];
            if(isZ) allZ = new byte[numShapes * 8];
            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);
                bbReader.Read(bigEndian, shp * 8, 8);
                ShapeTypes type = (ShapeTypes)bbReader.ReadInt32();
                //bbReader.Seek(4, SeekOrigin.Current);
                bbReader.Read(allCoords, shp * 16, 16);
                if(isZ)
                {
                    bbReader.Read(allZ, shp*8, 8);
                }
                if (isM)
                {
                    bbReader.Read(allM, shp*8, 8);
                }
                ShapeRange shape = new ShapeRange(FeatureTypes.Point);
                shape.StartIndex = shp;
                shape.ContentLength = 8;
                shape.NumPoints = 1;
                shape.NumParts = 1;
                ShapeIndices.Add(shape);
            }
            double[] vert = new double[2 * numShapes];
            Buffer.BlockCopy(allCoords, 0, vert, 0, numShapes*16);
            Vertex = vert;
            if(isM)
            {
                double[] m = new double[numShapes];
                Buffer.BlockCopy(allM, 0, m, 0, numShapes * 8);
                M = m;
            }
            if(isZ)
            {
                double[] z = new double[numShapes];
                Buffer.BlockCopy(allZ, 0, z, 0, numShapes * 8);
                Z = z;
            }
            for (int shp = 0; shp < numShapes; shp++)
            {
                PartRange part = new PartRange(vert, shp, 0, FeatureTypes.Point);
                part.NumVertices = 1;
                ShapeRange shape = ShapeIndices[shp];
                shape.Parts.Add(part);
                shape.Extent = new Extent(new[] {vert[shp*2], vert[shp*2 + 1], vert[shp*2], vert[shp*2 + 1]});
            }

                bbReader.Dispose();
            
            
            
  
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Tests to see if any vertices from the other shape are coincident with a segment from this line shape.
        /// </summary>
        /// <param name="lineShape"></param>
        /// <param name="otherShape"></param>
        /// <returns></returns>
        public static bool IntersectsVertex(ShapeRange lineShape, ShapeRange otherShape)
        {

            foreach (PartRange part in lineShape.Parts)
            {
                foreach (Segment segment in part.Segments)
                {
                    foreach (PartRange oPart in otherShape.Parts)
                    {
                        foreach (Vertex v in oPart)
                        {
                            if(segment.IntersectsVertex(v)) return true;
                        }
                    }
                    
                }
            }
            return false;

           
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Returns true if any segment from a line or polygon shape interesect any segments from the line or polygon shape.
        /// </summary>
        /// <param name="lineShape">A Line or Polygon shape</param>
        /// <param name="otherShape">Another line or polygon shape</param>
        /// <returns></returns>
        public static bool SegmentsIntersect(ShapeRange lineShape, ShapeRange otherShape)
        {
            if(lineShape.FeatureType != FeatureTypes.Line && lineShape.FeatureType != FeatureTypes.Polygon)
                throw new ArgumentException("Expected lineShape to be a line or polygon feature type, got " + lineShape.FeatureType);
            if (otherShape.FeatureType != FeatureTypes.Line && otherShape.FeatureType != FeatureTypes.Polygon)
                throw new ArgumentException("Expected otherShape to be a line or polygon feature type, got " + otherShape.FeatureType);


            foreach (PartRange part in lineShape.Parts)
            {
                foreach (Segment segment in part.Segments)
                {
                    foreach (PartRange oPart in otherShape.Parts)
                    {
                        int iSeg = 0;
                        foreach (Segment oSegment in oPart.Segments)
                        {
                            iSeg++;
                            if(iSeg == 279)
                            {
                                bool stop = true;
                            }
                            if (segment.Intersects(oSegment))
                            {
                                return true;
                            }
                        }
                    }
                }
            }

            // If the other segment is a polygon, we need to check the "

            return false;
        }
        // X Y MultiPoints: Total Length = 28 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 8        Integer     1           Little
        // Byte 12      Xmin                Double      1           Little
        // Byte 20      Ymin                Double      1           Little
        // Byte 28      Xmax                Double      1           Little
        // Byte 36      Ymax                Double      1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little


        // X Y M MultiPoints: Total Length = 34 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 28       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y*      Mmin                Double      1           Little
        // Byte Y + 8*  Mmax                Double      1           Little
        // Byte Y + 16* Marray              Double      NumPoints   Little
       
       
        
        // X Y Z M MultiPoints: Total Length = 44 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number  Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big       
        // Byte 8       Shape Type 18       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y       Zmin                Double      1           Little
        // Byte Y + 8   Zmax                Double      1           Little
        // Byte Y + 16  Zarray              Double      NumPoints   Little
        // Byte Z*      Mmin                Double      1           Little
        // Byte Z+8*    Mmax                Double      1           Little
        // Byte Z+16*   Marray              Double      NumPoints   Little


        private void FillPoints(string filename, IProgressHandler progressHandler)
        {
           
            // Check to ensure the filename is not null
            if (filename == null)
            {
                throw new NullReferenceException(MessageStrings.ArgumentNull_S.Replace("%S", filename));
            }

            if (File.Exists(filename) == false)
            {
                throw new FileNotFoundException(MessageStrings.FileNotFound_S.Replace("%S", filename));
            }

            // Get the basic header information.  
            ShapefileHeader header = new ShapefileHeader(filename);
            Extent = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });
            // Check to ensure that the filename is the correct shape type
            if (header.ShapeType != ShapeTypes.MultiPoint &&
                 header.ShapeType != ShapeTypes.MultiPointM &&
                 header.ShapeType != ShapeTypes.MultiPointZ)
            {
                throw new ArgumentException(MessageStrings.FileNotLines_S.Replace("%S", filename));

            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(filename);


            // This will set up a reader so that we can read values in huge chunks, which is much faster than one value at a time.
            IO.BufferedBinaryReader bbReader = new IO.BufferedBinaryReader(filename, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // The shapefile is empty so we can simply return here
                bbReader.Close();
                return;
            }


            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;

            byte[] bigEndians = new byte[numShapes * 8];
            byte[] allBounds = new byte[numShapes * 32];
        
            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool isM = (header.ShapeType == ShapeTypes.MultiPointZ || header.ShapeType == ShapeTypes.MultiPointM);
            bool isZ = (header.ShapeType == ShapeTypes.PolyLineZ);
            ByteBlock allZ = null;
            ByteBlock allM = null;
            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }
            int pointOffset = 0;
            for (int shp = 0; shp < numShapes; shp++)
            {

                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                // time: 200 ms
                ShapeRange shape = new ShapeRange(FeatureTypes.MultiPoint);


                shape.RecordNumber = bbReader.ReadInt32(false);       // Byte 0       Record Number       Integer     1           Big
                shape.ContentLength = bbReader.ReadInt32(false);      // Byte 4       Content Length      Integer     1           Big
                //bbReader.Read(bigEndians, shp * 8, 8);
                shape.ShapeType = (ShapeTypes)bbReader.ReadInt32();     
                shape.StartIndex = pointOffset;
                if (shape.ShapeType == ShapeTypes.NullShape)
                {
                    continue;
                }
                bbReader.Read(allBounds, shp * 32, 32);
                shape.NumParts = 1;                                    
                shape.NumPoints = bbReader.ReadInt32();                 
                allCoords.Read(shape.NumPoints * 16, bbReader);
                pointOffset += shape.NumPoints;

                if (header.ShapeType == ShapeTypes.MultiPointM)
                {
                    // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        double mMin = bbReader.ReadDouble();
                        double mMax = bbReader.ReadDouble();
                        //bbReader.Seek(16, SeekOrigin.Current);
                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }
                if (header.ShapeType == ShapeTypes.MultiPointZ)
                {
                    bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    double zMin = bbReader.ReadDouble();
                    double zMax = bbReader.ReadDouble();
                    // For Z shapefiles, the Z part is not optional.
                    if (allZ != null) allZ.Read(shape.NumPoints * 8, bbReader);

                    // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (hasM)
                    {
                        double mMin = bbReader.ReadDouble();
                        double mMax = bbReader.ReadDouble();
                        
                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }
                // Now that we have read all the values, create the geometries from the points and parts arrays.
                ShapeIndices.Add(shape);
            }
            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM) M = allM.ToDoubleArray();
            if (isZ) Z = allZ.ToDoubleArray();
            Array.Reverse(bigEndians);
            List<ShapeRange> shapes = ShapeIndices;
            double[] bounds = new double[numShapes * 4];
            Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            for (int shp = 0; shp < numShapes; shp++)
            {
                ShapeRange shape = shapes[shp];
                shape.Extent = new Extent(bounds, shp * 4);
                int endIndex = shape.NumPoints + shape.StartIndex;
                int startIndex = shape.StartIndex;
                int count = endIndex - startIndex;
                PartRange partR = new PartRange(vert, shape.StartIndex, 0, FeatureTypes.MultiPoint);
                partR.NumVertices = count;
                shape.Parts.Add(partR);
            }
            GC.Collect();
            bbReader.Dispose();
        }
Ejemplo n.º 14
0
 /// <summary>
 /// This cycles through all the vertices, which are stored as {X1, Y1, X2, Y2...Xn, Yn} and tests
 /// if any of those vertices falls within the polygon shape.
 /// </summary>
 /// <param name="polygonShape"></param>
 /// <param name="otherShape"></param>
 /// <returns></returns>
 public static bool ContainsVertex(ShapeRange polygonShape, ShapeRange otherShape)
 {
     
     foreach (PartRange otherPart in otherShape.Parts)
     {
         if(ContainsVertex(polygonShape, otherPart))
         {
             return true;
         }
     }
     return false;            
 }
Ejemplo n.º 15
0
        /// <summary>
        /// Appends the specified polygon to the graphics path.
        /// </summary>
        private static void BuildPolygon(double[] vertices, ShapeRange shpx, GraphicsPath borderPath, MapArgs args, bool clip)
        {
            double minX = args.MinX;
            double maxY = args.MaxY;
            double dx = args.Dx;
            double dy = args.Dy;
            borderPath.FillMode = FillMode.Winding;
            for (int prt = 0; prt < shpx.Parts.Count; prt++)
            {
                PartRange prtx = shpx.Parts[prt];
                int start = prtx.StartIndex;
                int end = prtx.EndIndex;
                List<double[]> points = new List<double[]>();
               
                for (int i = start; i <= end; i++)
                {
                    double[] pt = new double[2];
                    pt[X] = (vertices[i * 2] - minX) * dx;
                    pt[Y] = (maxY - vertices[i*2+1]) * dy;
                    points.Add(pt);
                }
                if (clip)
                {
                    points = SoutherlandHodgman.Clip(points);
                }
                List<System.Drawing.Point> intPoints = DuplicationPreventer.Clean(points);
                if (intPoints.Count < 2)
                {
                    points.Clear();
                    continue;
                }
                borderPath.StartFigure();
                System.Drawing.Point[] pointArray = intPoints.ToArray();
                borderPath.AddLines(pointArray);
                
                points.Clear();

                
            }


        }
Ejemplo n.º 16
0
        private static void FastBuildLine(GraphicsPath graphPath, double[] vertices, ShapeRange shpx, double minX, double maxY, double dx, double dy)
        {
            for (int prt = 0; prt < shpx.Parts.Count; prt++)
            {
                PartRange prtx = shpx.Parts[prt];
                int start = prtx.StartIndex;
                int end = prtx.EndIndex;
                List<System.Drawing.Point> partPoints = new List<System.Drawing.Point>();
                System.Drawing.Point previousPoint = new System.Drawing.Point();
                for (int i = start; i <= end; i++)
                {
                    if (double.IsNaN(vertices[i*2]) || double.IsNaN(vertices[i * 2 + 1])) continue;
                    System.Drawing.Point pt = new System.Drawing.Point();
                    pt.X = Convert.ToInt32((vertices[i * 2] - minX) * dx);
                    pt.Y = Convert.ToInt32((maxY - vertices[i * 2 + 1]) * dy);


                    if (i == 0 || (pt.X != previousPoint.X || pt.Y != previousPoint.Y))
                    {
                        // Don't add the same point twice
                        partPoints.Add(pt);
                        previousPoint = pt;
                    }
                }
                if (partPoints.Count < 2) continue; // we need two distinct points to make a line
                graphPath.StartFigure();
                graphPath.AddLines(partPoints.ToArray());
            }
        }
Ejemplo n.º 17
0
 /// <summary>
 /// This assumes that the byte order and shapetype have already been read.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="results"></param>
 private static void ReadPoint(Stream data, FeatureSetPack results)
 {
     ShapeRange sr = new ShapeRange(FeatureTypes.MultiPoint);
     PartRange prt = new PartRange(FeatureTypes.MultiPoint);
     prt.NumVertices = 1;
     sr.Parts.Add(prt);
     double[] coord = ReadDouble(data, 2);
     results.Add(coord, sr);
 }
Ejemplo n.º 18
0
        /// <summary>
        /// This calculations processes the intersections
        /// </summary>
        /// <param name="shape">The shape to do intersection calculations with.</param>
        public bool Intersects(ShapeRange shape)
        {
            // Extent check first.  If the extents don't intersect, then this doesn't intersect.
            if (!Extent.Intersects(shape.Extent)) return false;
            
            switch (FeatureType)
            {
                case FeatureTypes.Polygon:
                    PolygonShape.Epsilon = Epsilon;
                    return PolygonShape.Intersects(this, shape);
                case FeatureTypes.Line:
                    LineShape.Epsilon = Epsilon;
                    return LineShape.Intersects(this, shape);
                case FeatureTypes.Point:
                    PointShape.Epsilon = Epsilon;
                    return PointShape.Intersects(this, shape);
                default:
                    return false;
            }

        }
Ejemplo n.º 19
0
 private static void ReadMultiPoint(Stream data, FeatureSetPack results)
 {
     int count = ReadInt32(data);
     ShapeRange sr = new ShapeRange(FeatureTypes.MultiPoint);
     PartRange prt = new PartRange(FeatureTypes.MultiPoint);
     prt.NumVertices = count;
     sr.Parts.Add(prt);
     double[] vertices = new double[count*2];
     for(int iPoint = 0; iPoint < count; iPoint++)
     {
         data.ReadByte(); // ignore endian
         ReadInt32(data); // ignore geometry type
         double[] coord = ReadDouble(data, 2);
         Array.Copy(coord, 0, vertices, iPoint*2, 2);
     }
     results.Add(vertices, sr);
 }
Ejemplo n.º 20
0
        /// <summary>
        /// Occurs when the vertices are being re-calculated.
        /// </summary>
        protected virtual void OnInitializeVertices()
        {
            int count = 0;
            foreach (IFeature f in _features)
            {
                count += f.NumPoints;
            }
            _vertices = new double[count*2];
            int i = 0;
            foreach(IFeature f in _features)
            {
                IList<Coordinate> coords = f.Coordinates; // this should be all the coordinates, for all parts of the geometry.

                if (coords == null) continue;
                foreach (Coordinate c in coords)
                {
                    _vertices[i*2] = c.X;
                    _vertices[i*2+1] = c.Y;
                    // vertexValues.Add(c.Values); // essentially add a reference pointer to the internal array of values
                    i++;
                }
            }
            //_vertices = vertexValues.ToArray(); // not sure, but I bet arrays a smidge faster at indexed access than lists

             
            _shapeIndices = new List<ShapeRange>();
            int vIndex = 0;
            for(int shp = 0; shp < _features.Count; shp++) 
            {
                IFeature f = _features[shp];
                

                ShapeRange shx = new ShapeRange(FeatureType);
                shx.Extent = new Extent(f.Envelope);
                _shapeIndices.Add(shx);
                f.ShapeIndex = shx;
               
                // for simplicity in looping, there is always at least one part. 
                // That way, the shape range can be ignored and the parts loop used instead.
                shx.Parts = new List<PartRange>();
                int shapeStart = vIndex;
                for (int part = 0; part < f.NumGeometries; part++)
                {
                    PartRange prtx = new PartRange(_vertices, shapeStart, vIndex-shapeStart, FeatureType);
                    IBasicPolygon bp = f.GetBasicGeometryN(part) as IBasicPolygon;
                    if(bp != null)
                    {
                        // Account for the Shell
                        prtx.NumVertices = bp.Shell.NumPoints;
                        
                        vIndex += bp.Shell.NumPoints;
                        // The part range should be adjusted to no longer include the holes
                        foreach (var hole in bp.Holes)
                        {
                            PartRange holex = new PartRange(_vertices, shapeStart, vIndex - shapeStart, FeatureType);
                            holex.NumVertices = hole.NumPoints;
                            shx.Parts.Add(holex);
                            vIndex += hole.NumPoints;
                        }
                    }
                    else
                    {
                        int numPoints = f.GetBasicGeometryN(part).NumPoints;
                        
                        // This is not a polygon, so just add the number of points.
                        vIndex += numPoints;
                        prtx.NumVertices = numPoints;
                    }
                    shx.Parts.Add(prtx);
                }
                

            }
           // _vertices = vertexValues.ToArray();
            _verticesAreValid = true;
        }
Ejemplo n.º 21
0
 private static void ReadLineString(Stream data, FeatureSetPack results)
 {
     int count = ReadInt32(data);
     double[] coords = ReadDouble(data, 2 * count);
     ShapeRange lShp = new ShapeRange(FeatureTypes.Line);
     PartRange lPrt = new PartRange(FeatureTypes.Line);
     lPrt.NumVertices = count;
     lShp.Parts.Add(lPrt);
     results.Add(coords, lShp);
 }
Ejemplo n.º 22
0
 private static void ReadMultiLineString(Stream data, FeatureSetPack results)
 {
     int numLineStrings = ReadInt32(data);
     ShapeRange shp = new ShapeRange(FeatureTypes.Line);
     List<double[]> strings = new List<double[]>();
     int partOffset = 0;
     for(int iString = 0; iString < numLineStrings; iString++)
     {
         // Each of these needs to read a full WKBLineString
         data.Seek(5, SeekOrigin.Current); //ignore header
         int numPoints = ReadInt32(data);
         double[] coords = ReadDouble(data, 2*numPoints);
         PartRange lPrt = new PartRange(FeatureTypes.Line);
         lPrt.PartOffset = partOffset;
         lPrt.NumVertices = numPoints;
         shp.Parts.Add(lPrt);
         partOffset += coords.Length/2;
         strings.Add(coords);
     }
     double[] allVertices = new double[partOffset * 2];
     int offset = 0;
     foreach (double[] ring in strings)
     {
         Array.Copy(ring, 0, allVertices, offset, ring.Length);
         offset += ring.Length;
     }
     results.Add(allVertices, shp);
 }
Ejemplo n.º 23
0
        // X Y Poly Lines: Total Length = 28 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 3        Integer     1           Little
        // Byte 12      Xmin                Double      1           Little
        // Byte 20      Ymin                Double      1           Little
        // Byte 28      Xmax                Double      1           Little
        // Byte 36      Ymax                Double      1           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little


        // X Y M Poly Lines: Total Length = 34 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 23       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y*      Mmin                Double      1           Little
        // Byte Y + 8*  Mmax                Double      1           Little
        // Byte Y + 16* Marray              Double      NumPoints   Little
       
       
        
        // X Y Z M Poly Lines: Total Length = 44 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number  Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big       
        // Byte 8       Shape Type 13       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y       Zmin                Double      1           Little
        // Byte Y + 8   Zmax                Double      1           Little
        // Byte Y + 16  Zarray              Double      NumPoints   Little
        // Byte Z*      Mmin                Double      1           Little
        // Byte Z+8*    Mmax                Double      1           Little
        // Byte Z+16*   Marray              Double      NumPoints   Little

       


        private void FillPolygons(string filename, IProgressHandler progressHandler)
        {
           
            // Check to ensure the filename is not null
            if (filename == null)
            {
                throw new NullReferenceException(MessageStrings.ArgumentNull_S.Replace("%S", filename));
            }

            if (File.Exists(filename) == false)
            {
                throw new FileNotFoundException(MessageStrings.FileNotFound_S.Replace("%S", filename));
            }

            // Get the basic header information.  
            ShapefileHeader header = new ShapefileHeader(filename);
            Extent = new Extent(new[]{header.Xmin, header.Ymin, header.Xmax, header.Ymax});

            // Check to ensure that the filename is the correct shape type
            if (header.ShapeType != ShapeTypes.Polygon &&
                 header.ShapeType != ShapeTypes.PolygonM &&
                 header.ShapeType != ShapeTypes.PolygonZ)
            {
                throw new ArgumentException(MessageStrings.FileNotLines_S.Replace("%S", filename));

            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(filename);


            // This will set up a reader so that we can read values in huge chunks, which is much faster than one value at a time.
            IO.BufferedBinaryReader bbReader = new IO.BufferedBinaryReader(filename, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // The shapefile is empty so we can simply return here
                bbReader.Close();
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;
            
            int [] partOffsets = new int[numShapes];
            byte[] bigEndians = new byte[numShapes * 8];
            byte[] allBounds = new byte[numShapes * 32];

            ByteBlock allParts = new ByteBlock(BLOCKSIZE); // probably all will be in one block, but use a byteBlock just in case.
            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool isM = (header.ShapeType == ShapeTypes.PolyLineM || header.ShapeType == ShapeTypes.PolyLineZ);
            bool isZ = (header.ShapeType == ShapeTypes.PolyLineZ);
            ByteBlock allZ = null;
            ByteBlock allM = null;
            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }

            int pointOffset = 0;
            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                                                                    // Position     Value               Type        Number      Byte Order
                ShapeRange shape = new ShapeRange(FeatureTypes.Polygon); //-------------------------------------------------------------------- 
                shape.RecordNumber = bbReader.ReadInt32(false);     // Byte 0       Record Number       Integer     1           Big
                shape.ContentLength = bbReader.ReadInt32(false);    // Byte 4       Content Length      Integer     1           Big
                shape.ShapeType = (ShapeTypes)bbReader.ReadInt32(); // Byte 8       Shape Type          Integer     1           Little
                shape.StartIndex = pointOffset;
                if (shape.ShapeType == ShapeTypes.NullShape)
                {
                    continue;
                }
                bbReader.Read(allBounds, shp*32, 32);
                //double xMin = bbReader.ReadDouble();                // Byte 12      Xmin                Double      1           Little
               // double yMin = bbReader.ReadDouble();                // Byte 20      Ymin                Double      1           Little
                //double xMax = bbReader.ReadDouble();                // Byte 28      Xmax                Double      1           Little
                //double yMax = bbReader.ReadDouble();                // Byte 36      Ymax                Double      1           Little
                shape.NumParts = bbReader.ReadInt32();              // Byte 44      NumParts            Integer     1           Little
                //feature.NumPoints = bbReader.ReadInt32();             // Byte 48      NumPoints           Integer     1           Little
                shape.NumPoints = bbReader.ReadInt32();                                             
                
                // Create an envelope from the extents box in the file.
                //feature.Envelope = new Envelope(xMin, xMax, yMin, yMax);

                partOffsets[shp] = allParts.IntOffset();
                allParts.Read(shape.NumParts * 4, bbReader);
                allCoords.Read(shape.NumPoints * 16, bbReader);
                pointOffset += shape.NumPoints;



                if (header.ShapeType == ShapeTypes.PolygonM)
                {
                    // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        double mMin = bbReader.ReadDouble();
                        double mMax = bbReader.ReadDouble();
                        
                        if(allM != null)allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }

                if (header.ShapeType == ShapeTypes.PolygonZ)
                {
                    bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    double zMin = bbReader.ReadDouble();
                    double zMax = bbReader.ReadDouble();
                   
                    
                    // For Z shapefiles, the Z part is not optional.  
                    if (allZ != null) allZ.Read(shape.NumPoints * 8, bbReader);
                   
                    // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (hasM)
                    {
                        double mMin = bbReader.ReadDouble();
                        double mMax = bbReader.ReadDouble();
                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                    
                }
                ShapeIndices.Add(shape);
            }

            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM) M = allM.ToDoubleArray();
            if (isZ) Z = allZ.ToDoubleArray();
            List<ShapeRange> shapes = ShapeIndices;
            double[] bounds = new double[numShapes * 4];
            Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            int[] parts = allParts.ToIntArray();
            ProgressMeter = new ProgressMeter(ProgressHandler, "Testing Parts and Holes", numShapes);
            for (int shp = 0; shp < numShapes; shp++)
            {
                ShapeRange shape = shapes[shp];
                shape.Extent = new Extent(bounds, shp * 4);
                for (int part = 0; part < shape.NumParts; part++)
                {
                    int offset = partOffsets[shp];
                    int endIndex = shape.NumPoints + shape.StartIndex;
                    int startIndex = parts[offset + part] + shape.StartIndex;
                    if (part < shape.NumParts - 1) endIndex = parts[offset + part + 1] + shape.StartIndex;
                    int count = endIndex - startIndex;
                    PartRange partR = new PartRange(vert, shape.StartIndex, parts[offset + part], FeatureTypes.Polygon);
                    partR.NumVertices = count;
                    shape.Parts.Add(partR);
                }
                ProgressMeter.CurrentValue = shp;
            }
            ProgressMeter.Reset();
            GC.Collect();
        }