private unsafe IGeometry ReadPolygon(int oid) { var dataPtr = zeroPtr + recordHeaders[oid].Offset; var polygonRecord = (PolygonRecordP *)(dataPtr + 8); //First read all the rings int offset = polygonRecord->DataOffset; int parts = polygonRecord->NumParts; var rings = new ILinearRing[parts]; for (int part = 0; part < parts; ++part) { int points; if ((parts - part) > 1) { points = polygonRecord->PartOffsets[part + 1] - polygonRecord->PartOffsets[part]; } else { points = polygonRecord->NumPoints - polygonRecord->PartOffsets[part]; } if (points <= 1) { continue; } var ring = new Coordinate[points]; int index = 0; PointD *pointPtr = (PointD *)(dataPtr + 8 + offset + (polygonRecord->PartOffsets[part] << 4)); PointD point = *(pointPtr++); ring[index] = GeometryFactoryEx.CreateCoordinate(point.X, point.Y); ++index; while (index < points) { point = *(pointPtr++); ring[index] = GeometryFactoryEx.CreateCoordinate(point.X, point.Y); ++index; } // polygon should be closed, try to fix if (!ring[ring.Length - 1].Equals2D(ring[0])) { ring[ring.Length - 1] = GeometryFactoryEx.CreateCoordinate(ring[0].X, ring[0].Y); } rings[part] = GeometryFactory.CreateLinearRing(ring); } if (rings.Length == 1) //We only have one polygon { ILinearRing shell = rings[0]; if (rings.Length > 1) { var holes = new ILinearRing[rings.Length]; for (int i = 1; i < rings.Length; i++) { holes[i] = rings[i]; } return(GeometryFactory.CreatePolygon(shell, holes)); } return(GeometryFactory.CreatePolygon(shell, null)); } else { var polys = new List <IPolygon>(); ILinearRing shell = rings[0]; var holes = new List <ILinearRing>(); for (int i = 1; i < rings.Length; i++) { if (!GeometryFactory.IsCCW(rings[i].Coordinates)) { polys.Add(GeometryFactory.CreatePolygon(shell, null)); shell = rings[i]; } else { holes.Add(rings[i]); } } polys.Add(GeometryFactory.CreatePolygon(shell, holes.ToArray())); return(GeometryFactory.CreateMultiPolygon(polys.ToArray())); } }
/// <summary> /// Reads and parses the geometry with ID 'oid' from the ShapeFile /// </summary> /// <remarks><see cref="FilterDelegate">Filtering</see> is not applied to this method</remarks> /// <param name="oid">Object ID</param> /// <returns>geometry</returns> private unsafe IGeometry ReadGeometry(int oid) { if (_ShapeType == ShapeType.Polygon || _ShapeType == ShapeType.PolygonM || _ShapeType == ShapeType.PolygonZ) { return(ReadPolygon(oid)); } var dataPtr = zeroPtr + recordHeaders[oid].Offset + 8; var type = *((ShapeType *)dataPtr); if (type == ShapeType.Null) { return(null); } dataPtr += 4; if (IsPoint) { var x = *((double *)dataPtr); dataPtr += 8; var y = *((double *)dataPtr); return(GeometryFactory.CreatePoint(x, y)); } if (_ShapeType == ShapeType.Multipoint || _ShapeType == ShapeType.MultiPointM || _ShapeType == ShapeType.MultiPointZ) { dataPtr += 32; // min/max box var points = new List <IPoint>(); var nPoints = *(int *)dataPtr; // get the number of points dataPtr += 4; if (nPoints == 0) { return(null); } for (var i = 0; i < nPoints; i++) { var x = *((double *)dataPtr); dataPtr += 8; var y = *((double *)dataPtr); dataPtr += 8; points.Add(GeometryFactory.CreatePoint(x, y)); } return(GeometryFactory.CreateMultiPoint(points.ToArray())); } if (_ShapeType == ShapeType.PolyLine || _ShapeType == ShapeType.Polygon || _ShapeType == ShapeType.PolyLineM || _ShapeType == ShapeType.PolygonM || _ShapeType == ShapeType.PolyLineZ || _ShapeType == ShapeType.PolygonZ) { dataPtr += 32; // min/max int nParts = *(int *)dataPtr; // get number of parts (segments) dataPtr += 4; if (nParts == 0) { return(null); } int nPoints = *((int *)dataPtr); // get number of points dataPtr += 4; var segments = new int[nParts + 1]; //Read in the segment indexes for (int b = 0; b < nParts; b++) { segments[b] = *((int *)dataPtr); dataPtr += 4; } //add end point segments[nParts] = nPoints; if ((int)_ShapeType % 10 == 3) { var mline = new List <ILineString>(); for (var lineId = 0; lineId < nParts; lineId++) { var line = new List <Coordinate>(); for (var i = segments[lineId]; i < segments[lineId + 1]; i++) { var x = *((double *)dataPtr); dataPtr += 8; var y = *((double *)dataPtr); dataPtr += 8; line.Add(GeometryFactoryEx.CreateCoordinate(x, y)); } //line.Vertices.Add(new SharpMap.Geometries.Point( mline.Add(GeometryFactory.CreateLineString(line.ToArray())); } if (mline.Count == 1) { return(mline[0]); } return(GeometryFactory.CreateMultiLineString(mline.ToArray())); } // TODO: check it! //(_ShapeType == ShapeType.Polygon etc...) { //First read all the rings //List<SharpMap.Geometries.LinearRing> rings = new List<SharpMap.Geometries.LinearRing>(); var rings = new List <ILinearRing>(); for (int RingID = 0; RingID < nParts; RingID++) { //SharpMap.Geometries.LinearRing ring = new SharpMap.Geometries.LinearRing(); var ring = new List <Coordinate>(); for (int i = segments[RingID]; i < segments[RingID + 1]; i++) { ring.Add(GeometryFactoryEx.CreateCoordinate(brShapeFile.ReadDouble(), brShapeFile.ReadDouble())); } // polygon should be closed, try to fix if (!ring[ring.Count - 1].Equals2D(ring[0])) { ring.Add(GeometryFactoryEx.CreateCoordinate(ring[0].X, ring[0].Y)); } //ring.Vertices.Add(new SharpMap.Geometries.Point rings.Add(GeometryFactory.CreateLinearRing(ring.ToArray())); } var IsCounterClockWise = new bool[rings.Count]; int PolygonCount = 0; for (int i = 0; i < rings.Count; i++) { IsCounterClockWise[i] = GeometryFactory.IsCCW(rings[i].Coordinates); if (!IsCounterClockWise[i]) { PolygonCount++; } } if (PolygonCount == 1) //We only have one polygon { ILinearRing shell = rings[0]; var holes = new List <ILinearRing>(); if (rings.Count > 1) { for (int i = 1; i < rings.Count; i++) { holes.Add(rings[i]); } } return(GeometryFactory.CreatePolygon(shell, holes.ToArray())); } else { var polys = new List <IPolygon>(); ILinearRing shell = rings[0]; var holes = new List <ILinearRing>(); for (int i = 1; i < rings.Count; i++) { if (!IsCounterClockWise[i]) { polys.Add(GeometryFactory.CreatePolygon(shell, null)); shell = rings[i]; } else { holes.Add(rings[i]); } } polys.Add(GeometryFactory.CreatePolygon(shell, holes.ToArray())); return(GeometryFactory.CreateMultiPolygon(polys.ToArray())); } } } else { throw (new ApplicationException("Shapefile type " + _ShapeType.ToString() + " not supported")); } }