Exemplo n.º 1
0
        /// <summary>
        /// Creates a <see cref="IMultiPolygon"/> using the next token in the stream.
        /// </summary>
        /// <param name="tokenizer">tokenizer over a stream of text in Well-known Text
        /// format. The next tokens must form a MultiPolygon.</param>
        /// <param name="factory">The factory to create the result geometry</param>
        /// <returns>a <code>MultiPolygon</code> specified by the next token in the 
        /// stream, or if if the coordinates used to create the <see cref="IPolygon"/>
        /// shells and holes do not form closed linestrings.</returns>
        private static IMultiPolygon ReadMultiPolygonText(WktStreamTokenizer tokenizer, IGeometryFactory factory)
        {
            var polygons = new List<IPolygon>();
            string nextToken = GetNextEmptyOrOpener(tokenizer);
            if (nextToken == "EMPTY")
                return factory.CreateMultiPolygon(polygons.ToArray());

            var polygon = ReadPolygonText(tokenizer, factory);
            polygons.Add(polygon);
            nextToken = GetNextCloserOrComma(tokenizer);
            while (nextToken == ",")
            {
                polygon = ReadPolygonText(tokenizer, factory);
                polygons.Add(polygon);
                nextToken = GetNextCloserOrComma(tokenizer);
            }
            return factory.CreateMultiPolygon(polygons.ToArray());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum = file.ReadInt32();
            type = (ShapeGeometryType) Enum.Parse(typeof(ShapeGeometryType), shapeTypeNum.ToString());
            if (type == ShapeGeometryType.NullShape)
                return geometryFactory.CreatePolygon(null, null);

            if (!(type == ShapeGeometryType.Polygon  || type == ShapeGeometryType.PolygonM ||
                  type == ShapeGeometryType.PolygonZ || type == ShapeGeometryType.PolygonZM))	
                throw new ShapefileException("Attempting to load a non-polygon as polygon.");

            // Read and for now ignore bounds.
            int bblength = GetBoundingBoxLength();
            bbox = new double[bblength];
            for (; bbindex < 4; bbindex++)
            {
                double d = file.ReadDouble();
                bbox[bbindex] = d;
            }
            
            int[] partOffsets;        
            int numParts = file.ReadInt32();
            int numPoints = file.ReadInt32();
            partOffsets = new int[numParts];
            for (int i = 0; i < numParts; i++)
                partOffsets[i] = file.ReadInt32();

            ArrayList shells = new ArrayList();
            ArrayList holes = new ArrayList();

            int start, finish, length;
            for (int part = 0; part < numParts; part++)
            {
                start = partOffsets[part];
                if (part == numParts - 1)
                    finish = numPoints;
                else finish = partOffsets[part + 1];
                length = finish - start;
                CoordinateList points = new CoordinateList();
                points.Capacity = length;
                for (int i = 0; i < length; i++)
                {
                    ICoordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble() );					
                    geometryFactory.PrecisionModel.MakePrecise( external);
                    ICoordinate internalCoord = external;

                    // Thanks to Abhay Menon!
                    if (!Double.IsNaN(internalCoord.Y) && !Double.IsNaN(internalCoord.X))
                        points.Add(internalCoord, false);
                }

                if (points.Count > 2) // Thanks to Abhay Menon!
                {
                    if (points[0].Distance(points[points.Count - 1]) > .00001)
                        points.Add(new Coordinate(points[0]));
                    else if (points[0].Distance(points[points.Count - 1]) > 0.0)
                        points[points.Count - 1].CoordinateValue = points[0];

                    ILinearRing ring = geometryFactory.CreateLinearRing(points.ToArray());

                    // If shape have only a part, jump orientation check and add to shells
                    if (numParts == 1)
                        shells.Add(ring);
                    else
                    {
                        // Orientation check
                        if (CGAlgorithms.IsCCW(points.ToArray()))
                             holes.Add(ring);
                        else shells.Add(ring);
                    }                    
                }
            }

            // Now we have a list of all shells and all holes
            ArrayList holesForShells = new ArrayList(shells.Count);
            for (int i = 0; i < shells.Count; i++)
                holesForShells.Add(new ArrayList());

            // Find holes
            for (int i = 0; i < holes.Count; i++)
            {
                ILinearRing testRing = (ILinearRing) holes[i];
                ILinearRing minShell = null;
                IEnvelope minEnv = null;
                IEnvelope testEnv = testRing.EnvelopeInternal;
                ICoordinate testPt = testRing.GetCoordinateN(0);
                ILinearRing tryRing;
                for (int j = 0; j < shells.Count; j++)
                {
                    tryRing = (ILinearRing) shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                        minEnv = minShell.EnvelopeInternal;
                    bool isContained = false;
                    CoordinateList coordList = new CoordinateList(tryRing.Coordinates);
                    if (tryEnv.Contains(testEnv) && 
                       (CGAlgorithms.IsPointInRing(testPt, coordList.ToArray()) || (PointInList(testPt, coordList)))) 				
                        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;             

                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        ArrayList holesForThisShell = (ArrayList) holesForShells[j];
                        holesForThisShell.Add(testRing);
                    }
                }
            }

            IPolygon[] polygons = new IPolygon[shells.Count];
            for (int i = 0; i < shells.Count; i++)
                polygons[i] = (geometryFactory.CreatePolygon((ILinearRing) shells[i], 
                    (ILinearRing[]) ((ArrayList) holesForShells[i]).ToArray(typeof(ILinearRing))));

            if (polygons.Length == 1)
                 geom = polygons[0];
            else geom = geometryFactory.CreateMultiPolygon(polygons);
            GrabZMValues(file);
            return geom;
        }
        /// <summary>
        /// See http://www.gaia-gis.it/gaia-sins/BLOB-Geometry.html
        /// for the specification of the spatialite BLOB geometry format
        /// Derived from WKB, but unfortunately it is not practical to reuse existing
        /// WKB encoding/decoding code
        /// </summary>
        /// <param name="spatialliteGeom">The geometry blob</param>
        /// <param name="factory">The factory to create the result geometry</param>
        /// <returns>A geometry</returns>
        public static IGeometry Parse(byte[] spatialliteGeom, IGeometryFactory factory)
        {
            var nBytes = spatialliteGeom.Length;
            if (spatialliteGeom.Length < 44
            || spatialliteGeom[0] != 0
            || spatialliteGeom[38] != 0x7C
            || spatialliteGeom[nBytes - 1] != 0xFE)
                throw new ApplicationException("Corrupt SpatialLite geom");

            bool isLittleEndian = spatialliteGeom[1] == 0x01;
            if (spatialliteGeom[1] != 0x00 && spatialliteGeom[1] != 0x01)
                throw new ApplicationException("Corrupt SpatialLite geom");

            int idx = 39;
            int nGType = ReadUInt32(spatialliteGeom, ref idx, isLittleEndian);

            if (nGType < 1 || nGType > 7)
                throw new ApplicationException("Unsupported geom type!");

            /* -------------------------------------------------------------------- */
            /*      Point                                                           */
            /* -------------------------------------------------------------------- */
            if (nGType == 1)
            {
                return factory.CreatePoint(ReadPoint(spatialliteGeom, ref idx, isLittleEndian));
            }
            /* -------------------------------------------------------------------- */
            /*      LineString                                                      */
            /* -------------------------------------------------------------------- */
            else if (nGType == 2)
            {
                return ReadLineString(spatialliteGeom, ref idx, isLittleEndian, factory);
            }
            /* -------------------------------------------------------------------- */
            /*      Polygon                                                      */
            /* -------------------------------------------------------------------- */
            else if (nGType == 3)
            {
                return ReadPolygon(spatialliteGeom, ref idx, isLittleEndian, factory);
            }
            /* -------------------------------------------------------------------- */
            /*      MultiPoint                          */
            /* -------------------------------------------------------------------- */
            else if (nGType == 4)
            {
                List<GeoAPI.Geometries.IPoint> pts = new List<GeoAPI.Geometries.IPoint>();
                int numGeoms = ReadUInt32(spatialliteGeom, ref idx, isLittleEndian);
                for (int i = 0; i < numGeoms; i++)
                {
                    if (spatialliteGeom[idx] != 0x69)
                        throw new ApplicationException("FormatError in SpatiaLIteGeom");
                    idx++;
                    int gt = ReadUInt32(spatialliteGeom, ref idx, isLittleEndian);
                    if (gt != 1)
                        throw new ApplicationException("MultiPoint must Contain Point entities");

                    pts.Add(factory.CreatePoint(ReadPoint(spatialliteGeom, ref idx, isLittleEndian)));
                }
                return factory.CreateMultiPoint(pts.ToArray());
            }
            /* -------------------------------------------------------------------- */
            /*      MultiLineString                          */
            /* -------------------------------------------------------------------- */
            else if (nGType == 5)
            {
                List<GeoAPI.Geometries.ILineString> lss = new List<GeoAPI.Geometries.ILineString>();
                int numGeoms = ReadUInt32(spatialliteGeom, ref idx, isLittleEndian);
                for (int i = 0; i < numGeoms; i++)
                {
                    if (spatialliteGeom[idx] != 0x69)
                        throw new ApplicationException("FormatError in SpatiaLIteGeom");
                    idx++;
                    int gt = ReadUInt32(spatialliteGeom, ref idx, isLittleEndian);
                    if (gt != 2)
                        throw new ApplicationException("MultiLineString must contain LineString Entities");
                    lss.Add(ReadLineString(spatialliteGeom, ref idx, isLittleEndian, factory));
                }
                return factory.CreateMultiLineString(lss.ToArray());
            }
            /* -------------------------------------------------------------------- */
            /*      MultiPolygon                                                      */
            /* -------------------------------------------------------------------- */
            else if (nGType == 6)
            {
                List<GeoAPI.Geometries.IPolygon> polys = new List<GeoAPI.Geometries.IPolygon>();
                int numPolys = ReadUInt32(spatialliteGeom, ref idx, isLittleEndian);
                for (int i = 0; i < numPolys; i++)
                {
                    if (spatialliteGeom[idx] != 0x69)
                        throw new ApplicationException("FormatError in SpatiaLIteGeom");
                    idx++;
                    int gt = ReadUInt32(spatialliteGeom, ref idx, isLittleEndian);
                    if (gt != 3)
                        throw new ApplicationException("Multipolygon must contain Polygon Entities");

                    polys.Add(ReadPolygon(spatialliteGeom, ref idx, isLittleEndian, factory));
                }
                return factory.CreateMultiPolygon(polys.ToArray());
            }

            return null;
        }
Exemplo n.º 4
0
        /// <summary>
        /// Creates a Polygon or MultiPolygon from this Polygon shape.
        /// </summary>
        /// <param name="factory">The IGeometryFactory to use to create the new IGeometry.</param>
        /// <returns>The IPolygon or IMultiPolygon created from this shape.</returns>
        protected IGeometry FromPolygon(IGeometryFactory factory)
        {
            if (factory == null) factory = Geometry.DefaultFactory;
            List<ILinearRing> shells = new List<ILinearRing>();
            List<ILinearRing> holes = new List<ILinearRing>();
            foreach (PartRange part in _shapeRange.Parts)
            {
                List<Coordinate> coords = new List<Coordinate>();
                int i = part.StartIndex;
                foreach (Vertex d in part)
                {
                    Coordinate c = new Coordinate(d.X, d.Y);
                    if (M != null && M.Length > 0) c.M = M[i];
                    if (Z != null && Z.Length > 0) c.Z = Z[i];
                    i++;
                    coords.Add(c);
                }
                ILinearRing ring = factory.CreateLinearRing(coords);
                if (_shapeRange.Parts.Count == 1)
                {
                    shells.Add(ring);
                }
                else
                {
                    if (CgAlgorithms.IsCounterClockwise(ring.Coordinates))
                    {
                        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
            foreach (ILinearRing t in holes)
            {
                ILinearRing testRing = t;
                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(t);
                    }
                }
            }

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

            if (polygons.Length == 1)
            {
                return polygons[0];
            }
            // It's a multi part
            return factory.CreateMultiPolygon(polygons);
        }
Exemplo n.º 5
0
        /// <summary>  
        /// Creates a <c>MultiPolygon</c> using the next token in the stream.
        /// </summary>
        /// <param name="tokens">Tokenizer over a stream of text in Well-known Text
        ///   format. The next tokens must form a MultiPolygon Text.
        /// </param>
        /// <param name="factory"> </param>
        /// <returns>
        /// A <c>MultiPolygon</c> specified by the next
        /// token in the stream, or if if the coordinates used to create the
        /// <c>Polygon</c> shells and holes do not form closed linestrings.</returns>
        private IMultiPolygon ReadMultiPolygonText(IEnumerator<Token> tokens, IGeometryFactory factory)
        {
            string nextToken = GetNextEmptyOrOpener(tokens);
            if (nextToken.Equals("EMPTY"))
                return factory.CreateMultiPolygon(new IPolygon[]{});

            var polygons = new List<IPolygon>();
            var polygon = ReadPolygonText(tokens, factory);
            polygons.Add(polygon);
            nextToken = GetNextCloserOrComma(tokens);
            while (nextToken.Equals(","))
            {
                polygon = ReadPolygonText(tokens, factory);
                polygons.Add(polygon);
                nextToken = GetNextCloserOrComma(tokens);
            }
            return factory.CreateMultiPolygon(polygons.ToArray());
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a Polygon or MultiPolygon from this Polygon shape.
        /// </summary>
        /// <param name="factory">The IGeometryFactory to use to create the new IGeometry.</param>
        /// <returns>The IPolygon or IMultiPolygon created from this shape.</returns>
        protected IGeometry FromPolygon(IGeometryFactory factory)
        {
            if (factory == null) factory = Geometry.DefaultFactory;
            var shells = new List<ILinearRing>();
            var holes = new List<ILinearRing>();
            foreach (var part in _shapeRange.Parts)
            {
                var coords = GetCoordinates(part);
                var ring = factory.CreateLinearRing(coords);
                if (_shapeRange.Parts.Count == 1)
                {
                    shells.Add(ring);
                }
                else
                {
                    if (CgAlgorithms.IsCounterClockwise(ring.Coordinates))
                    {
                        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
            foreach (ILinearRing t in holes)
            {
                ILinearRing testRing = t;
                ILinearRing minShell = null;
                IEnvelope minEnv = null;
                IEnvelope testEnv = testRing.EnvelopeInternal;
                Coordinate testPt = testRing.Coordinates[0];
                for (int j = 0; j < shells.Count; j++)
                {
                    ILinearRing tryRing = shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                        minEnv = minShell.EnvelopeInternal;
                    var isContained = tryEnv.Contains(testEnv)
                                       && (CgAlgorithms.IsPointInRing(testPt, tryRing.Coordinates)
                                           || (PointInList(testPt, tryRing.Coordinates)));

                    // 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(t);
                    }
                }
            }

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

            if (polygons.Length == 1)
            {
                return polygons[0];
            }
            // It's a multi part
            return factory.CreateMultiPolygon(polygons);
        }
Exemplo n.º 7
0
		/// <summary>
		/// Transforms a <see cref="MultiPolygon" /> object.
		/// </summary>
		/// <param name="factory"></param>
		/// <param name="polys"></param>
		/// <param name="transform"></param>
		/// <returns></returns>
        public static IMultiPolygon TransformMultiPolygon(IGeometryFactory factory,
            IMultiPolygon polys, IMathTransform transform)
		{
			List<IPolygon> polygons = new List<IPolygon>(polys.Geometries.Length);
			foreach (IPolygon p in polys.Geometries)
			{
			    IPolygon item = TransformPolygon(factory, p, transform);
			    polygons.Add(item);
			}
		    return factory.CreateMultiPolygon(polygons.ToArray());
		}
 /// <summary>
 /// Computes the transformation of the source geometry.
 /// </summary>
 /// <param name="source">The source geometry.</param>
 /// <returns>The geometry in the specified reference system.</returns>
 private IMultiPolygon Compute(IMultiPolygon source)
 {
     return(_factory.CreateMultiPolygon(source.Select(item => Compute(item)),
                                        _metadataPreservation ? source.Metadata : null));
 }
Exemplo n.º 9
0
 internal static NTSMultiPolygon ToNTSMultiPolygon(Geometries.MultiPolygon geom,
     IGeometryFactory factory)
 {
     NTSPolygon[] polygons = new NTSPolygon[geom.Polygons.Count];
     int index = 0;
     foreach (Geometries.Polygon polygon in geom.Polygons)
         polygons[index++] = ToNTSPolygon(polygon, factory);
     return factory.CreateMultiPolygon(polygons) as NTSMultiPolygon;
 }
Exemplo n.º 10
0
        private static IMultiPolygon CreateWKBMultiPolygon(BinaryReader reader, WkbByteOrder byteOrder, IGeometryFactory factory)
        {
            // Get the number of Polygons.
            var numPolygons = (int) ReadUInt32(reader, byteOrder);

            // Create a new array for the Polygons.
            var polygons = new IPolygon[numPolygons];

            // Loop on the number of polygons.
            for (var i = 0; i < numPolygons; i++)
            {
                // read polygon header
                reader.ReadByte();
                ReadUInt32(reader, byteOrder);

                // TODO: Validate type

                // Create the next polygon and add it to the array.
                polygons[i] = CreateWKBPolygon(reader, byteOrder, factory);
            }

            //Create and return the MultiPolygon.
            return factory.CreateMultiPolygon(polygons);
        }
Exemplo n.º 11
0
		/// <summary>
		/// Reads a stream and converts the shapefile record to an equilivent geometry object.
		/// </summary>
		/// <param name="file">The stream to read.</param>
		/// <param name="geometryFactory">The geometry factory to use when making the object.</param>
		/// <returns>The Geometry object that represents the shape file record.</returns>
		public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
		{
			int shapeTypeNum = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());
            if ( ! ( shapeType == ShapeGeometryTypes.Polygon  || shapeType == ShapeGeometryTypes.PolygonM ||
                     shapeType == ShapeGeometryTypes.PolygonZ || shapeType == ShapeGeometryTypes.PolygonZM))	
				throw new ShapefileException("Attempting to load a non-polygon as polygon.");

			// Read and for now ignore bounds.
			double[] box = new double[4];
			for (int i = 0; i < 4; i++) 
				box[i] = file.ReadDouble();

		    int numParts = file.ReadInt32();
			int numPoints = file.ReadInt32();
			int[] partOffsets = new int[numParts];
			for (int i = 0; i < numParts; i++)
				partOffsets[i] = file.ReadInt32();

			ArrayList shells = new ArrayList();
			ArrayList holes = new ArrayList();

		    for (int part = 0; part < numParts; part++)
			{
				int start = partOffsets[part];
			    int finish;
			    if (part == numParts - 1)
					 finish = numPoints;
				else finish = partOffsets[part + 1];
				int length = finish - start;
                CoordinateList points = new CoordinateList();
				for (int i = 0; i < length; i++)
				{
					Coordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble() );					
                    new PrecisionModel(geometryFactory.PrecisionModel).MakePrecise(external);
                    Coordinate internalCoord = external;
					points.Add(internalCoord);
				}

				ILinearRing ring = geometryFactory.CreateLinearRing(points.ToArray());
				
                // If shape have only a part, jump orientation check and add to shells
                if (numParts == 1)
                    shells.Add(ring);
                else
                {
                    // Orientation check
                    if (CGAlgorithms.IsCounterClockwise(points.ToArray()))
                        holes.Add(ring);
                    else shells.Add(ring);
                }
			}

			// Now we have a list of all shells and all holes
			ArrayList holesForShells = new ArrayList(shells.Count);
			for (int i = 0; i < shells.Count; i++)
				holesForShells.Add(new ArrayList());
			// Find holes
			for (int i = 0; i < holes.Count; i++)
			{
				LinearRing testRing = (LinearRing) holes[i];
				LinearRing minShell = null;
				IEnvelope minEnv = null;
				IEnvelope testEnv = testRing.EnvelopeInternal;
				Coordinate testPt = testRing.GetCoordinateN(0);
				LinearRing tryRing;
				for (int j = 0; j < shells.Count; j++)
				{
					tryRing = (LinearRing) shells[j];
					IEnvelope tryEnv = tryRing.EnvelopeInternal;
					if (minShell != null) 
						minEnv = minShell.EnvelopeInternal;
					bool isContained = false;
					CoordinateList coordList = new CoordinateList(tryRing.Coordinates);
					if (tryEnv.Contains(testEnv)
                        && (CGAlgorithms.IsPointInRing(testPt, coordList.ToArray()) 
                        || (PointInList(testPt, coordList)))) 				
						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;

                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        ArrayList holesForThisShell = (ArrayList)holesForShells[j];
                        holesForThisShell.Add(holes[i]);
                    }
				}
			}

			IPolygon[] polygons = new Polygon[shells.Count];
			for (int i = 0; i < shells.Count; i++)			
				polygons[i] = geometryFactory.CreatePolygon((LinearRing) shells[i], 
                    (LinearRing[])((ArrayList) holesForShells[i]).ToArray(typeof(LinearRing)));
        
			if (polygons.Length == 1)
				return polygons[0];
			// It's a multi part
			return geometryFactory.CreateMultiPolygon(polygons);
		}
Exemplo n.º 12
0
 /// <summary>
 /// Transforms a <see cref="IMultiPolygon" /> object.
 /// </summary>
 /// <param name="factory">The factory to create the new <see cref="IMultiPolygon"/></param>
 /// <param name="polys">The input <see cref="IMultiPolygon"/></param>
 /// <param name="transform">The <see cref="IMathTransform"/></param>
 /// <returns>A transformed <see cref="IMultiPolygon"/></returns>
 public static IMultiPolygon TransformMultiPolygon(IGeometryFactory factory,
     IMultiPolygon polys, IMathTransform transform)
 {
     var geometries = polys.Geometries;
     var polygons = new List<IPolygon>(geometries.Length);
     foreach (var p in geometries)
     {
         var item = TransformPolygon(factory, (IPolygon)p, transform);
         polygons.Add(item);
     }
     return factory.CreateMultiPolygon(polygons.ToArray());
 }
Exemplo n.º 13
0
        private static IGeometry ParseWkbMultiPolygon(byte[] blob, ref int offset, IGeometryFactory factory, ReadCoordinatesFunction readCoordinates, GaiaImport gaiaImport)
        {
            var number = gaiaImport.GetInt32(blob, ref offset);
            var polygons = new IPolygon[number];
            for (var i = 0; i < number; i++)
            {
                if (blob[offset++] != (byte)GaiaGeoBlobMark.GAIA_MARK_ENTITY)
                    throw new Exception();

                var gt = gaiaImport.GetInt32(blob, ref offset);
                if (ToBaseGeometryType((GaiaGeoGeometry)gt) != GaiaGeoGeometry.GAIA_POLYGON)
                    throw new Exception();

                //Since Uncompressed MultiGeom can contain compressed we need to set it here also
                readCoordinates = SetReadCoordinatesFunction(gaiaImport, (GaiaGeoGeometry)gt);


                polygons[i] = ParseWkbPolygon(blob, ref offset, factory, readCoordinates, gaiaImport);
            }
            return factory.CreateMultiPolygon(polygons);
        }
        /// <summary>
        /// Transforms a <see cref="GeoAPI.Geometries.IMultiPolygon"/>.
        /// </summary>
        /// <param name="polys">MultiPolygon to transform</param>
        /// <param name="from">Source Projection</param>
        /// <param name="to">Target Projection</param>
        /// <param name="toFactory">The factory to create geometries for <paramref name="to"/></param>
        /// <returns>Transformed MultiPolygon</returns>
        public static IMultiPolygon TransformMultiPolygon(IMultiPolygon polys, ProjectionInfo from, ProjectionInfo to, IGeometryFactory toFactory)
        {
            var pOut = new IPolygon[polys.Count];
            for (var i = 0; i < polys.Count; i++)
                pOut[i] = TransformPolygon((IPolygon)polys.GetGeometryN(i), from, to, toFactory);

            return toFactory.CreateMultiPolygon(pOut);
        }
Exemplo n.º 15
0
 /// <summary>
 /// Transforms a <see cref="GeoAPI.Geometries.IMultiPolygon"/>.
 /// </summary>
 /// <param name="polys">MultiPolygon to transform</param>
 /// <param name="transform">MathTransform</param>
 /// <param name="targetFactory">The factory to create the target geometry</param>
 /// <returns>Transformed MultiPolygon</returns>
 public static IMultiPolygon TransformMultiPolygon(IMultiPolygon polys, IMathTransform transform, IGeometryFactory targetFactory)
 {
     var polyList = new IPolygon[polys.NumGeometries];
     for (var i = 0; i < polys.NumGeometries; i++)
     {
         var poly = (IPolygon) polys[i];
         polyList[i] = TransformPolygon(poly, transform, targetFactory);
     }
     return targetFactory.CreateMultiPolygon(polyList);
 }
Exemplo n.º 16
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="totalRecordLength">Total length of the record we are about to read</param>
        /// <param name="factory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory factory)
        {
            int totalRead = 0;
            var type = (ShapeGeometryType)ReadInt32(file, totalRecordLength, ref totalRead);
            if (type == ShapeGeometryType.NullShape)
                return factory.CreatePolygon(null, null);

            if (type != ShapeType)
                throw new ShapefileException(string.Format("Encountered a '{0}' instead of a  '{1}'", type, ShapeType));

            // Read and for now ignore bounds.
            var bblength = GetBoundingBoxLength();
            boundingBox = new double[bblength];
            for (; boundingBoxIndex < 4; boundingBoxIndex++)
                boundingBox[boundingBoxIndex] = ReadDouble(file, totalRecordLength, ref totalRead);

            var numParts = ReadInt32(file, totalRecordLength, ref totalRead);
            var numPoints = ReadInt32(file, totalRecordLength, ref totalRead);
            var partOffsets = new int[numParts];
            for (var i = 0; i < numParts; i++)
                partOffsets[i] = ReadInt32(file, totalRecordLength, ref totalRead);

            var skippedList = new HashSet<int>();

            //var allPoints = new List<Coordinate>();
            var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true);
            var pm = factory.PrecisionModel;
            for (var part = 0; part < numParts; part++)
            {
                var start = partOffsets[part];
                var finish = (part == numParts - 1) 
                    ? numPoints 
                    : partOffsets[part + 1];
                
                var length = finish - start;
                for (var i = 0; i < length; i++)
                {
                    var x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead));
                    var y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead));

                    // Thanks to Abhay Menon!
                    if (!(Coordinate.NullOrdinate.Equals(x) || Coordinate.NullOrdinate.Equals(y)))
                        buffer.AddCoordinate(x, y);
                    else
                        skippedList.Add(start + i);
                }
                //Add a marker that we have finished one part of the geometry
                buffer.AddMarker();
            }

            // Trond Benum: We have now read all the parts, let's read optional Z and M values
            // and populate Z in the coordinate before we start manipulating the segments
            // We have to track corresponding optional M values and set them up in the 
            // Geometries via ICoordinateSequence further down.
            GetZMValues(file, totalRecordLength, ref totalRead, buffer, skippedList);

            // Get the resulting sequences
            var sequences = buffer.ToSequences(factory.CoordinateSequenceFactory);
            var shells = new List<ILinearRing>();
            var holes = new List<ILinearRing>();
            for (var i = 0; i < sequences.Length; i++)
            {
                //Skip garbage input data with 0 points
                if (sequences[i].Count < 1) continue;

                var tmp = EnsureClosedSequence(sequences[i], factory.CoordinateSequenceFactory);
                var ring = factory.CreateLinearRing(tmp);
                if (ring.IsCCW)
                    holes.Add(ring);
                else
                    shells.Add(ring);
            }

            // Ensure the ring is encoded right
            if (shells.Count == 0 && holes.Count == 1)
            {
                shells.Add(factory.CreateLinearRing(holes[0].CoordinateSequence.Reversed()));
                holes.Clear();
            }


            // Now we have lists of all shells and all holes
            var holesForShells = new List<List<ILinearRing>>(shells.Count);
            for (var i = 0; i < shells.Count; i++)
                holesForShells.Add(new List<ILinearRing>());

            //Thanks to Bruno.Labrecque
            //Sort shells by area, rings should only be added to the smallest shell, that contains the ring
            shells.Sort(ProbeLinearRing);

            // Find holes
            foreach (var testHole in holes)
            {
                var testEnv = testHole.EnvelopeInternal;
                var testPt = testHole.GetCoordinateN(0);
                
                //We have the shells sorted
                for (var j = 0; j < shells.Count; j++)
                {
                    var tryShell = shells[j];
                    var tryEnv = tryShell.EnvelopeInternal;
                    var isContained = tryEnv.Contains(testEnv) && CGAlgorithms.IsPointInRing(testPt, tryShell.Coordinates);

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        var holesForThisShell = holesForShells[j];
                        holesForThisShell.Add(testHole);
                        
                        //Suggested by Bruno.Labrecque
                        //A LinearRing should only be added to one outer shell
                        break;
                    }
                }
            }

            var polygons = new IPolygon[shells.Count];
            for (var i = 0; i < shells.Count; i++)
                polygons[i] = (factory.CreatePolygon(shells[i], holesForShells[i].ToArray()));

            if (polygons.Length == 1)
                geom = polygons[0];
            else 
                geom = factory.CreateMultiPolygon(polygons);
      
            return geom;
        }
Exemplo n.º 17
0
        public IGeometry ParseGeometry(JsonReader reader)
        {
            GeoJsonObjectType?geometryType = null;
            List <object>     coords       = null;
            List <IGeometry>  geoms        = null;

            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.EndObject)
                {
                    // we are at the end of the geometry block, do not read further
                    break;
                }

                // read the tokens, type may come before coordinates or geometries as pr spec
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    if ((string)reader.Value == "type" && geometryType == null)
                    {
                        // get the type name
                        reader.Read();
                        geometryType = (GeoJsonObjectType)Enum.Parse(typeof(GeoJsonObjectType), (string)reader.Value, true);
                    }
                    else if ((String)reader.Value == "geometries")
                    {
                        // only geom collection has "geometries"
                        reader.Read();  //read past start array tag
                        geoms = ParseGeomCollection(reader);
                    }
                    else if ((String)reader.Value == "coordinates")
                    {
                        reader.Read(); // read past start array tag
                        coords = ReadCoordinates(reader);
                    }
                }
            }

            // check data readed correctly
            if (geometryType == null)
            {
                return(null);
            }
            switch (geometryType)
            {
            case GeoJsonObjectType.GeometryCollection:
                if (geoms == null)
                {
                    return(null);
                }
                break;

            default:
                if (coords == null)
                {
                    return(null);
                }
                break;
            }

            // build geom
            switch (geometryType)
            {
            case GeoJsonObjectType.Point:
            {
                Coordinate coordinate = PointCoords(coords);
                return(_factory.CreatePoint(coordinate));
            }

            case GeoJsonObjectType.LineString:
            {
                Coordinate[] coordinates = LineStringCoords(coords);
                return(_factory.CreateLineString(coordinates));
            }

            case GeoJsonObjectType.Polygon:
            {
                List <Coordinate[]> coordinates = PolygonCoords(coords);
                return(CreatePolygon(coordinates));
            }

            case GeoJsonObjectType.MultiPoint:
            {
                Coordinate[] coordinates = LineStringCoords(coords);
                return(_factory.CreateMultiPoint(coordinates));
            }

            case GeoJsonObjectType.MultiLineString:
            {
                List <ILineString> list = new List <ILineString>();
                foreach (Coordinate[] coordinates in PolygonCoords(coords))
                {
                    ILineString lineString = _factory.CreateLineString(coordinates);
                    list.Add(lineString);
                }
                return(_factory.CreateMultiLineString(list.ToArray()));
            }

            case GeoJsonObjectType.MultiPolygon:
            {
                List <IPolygon> list = new List <IPolygon>();
                foreach (List <Coordinate[]> coordinates in MultiPolygonCoords(coords))
                {
                    IPolygon polygon = CreatePolygon(coordinates);
                    list.Add(polygon);
                }
                return(_factory.CreateMultiPolygon(list.ToArray()));

                ;
            }

            case GeoJsonObjectType.GeometryCollection:
            {
// ReSharper disable once PossibleNullReferenceException
                return(_factory.CreateGeometryCollection(geoms.ToArray()));
            }
            }
            return(null);
        }