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