private bool AddPointToShapeFile(double x, double y, MapWinGIS.Shapefile shpFile, int shpIndex, int insertIndex) { try { MapWinGIS.Point p; //start editing shapes shpFile.StartEditingShapes(true, null); MapWinGIS.Shape shp = shpFile.get_Shape(shpIndex); p = new MapWinGIS.Point(); p.x = x; p.y = y; if (!shp.InsertPoint(p, ref insertIndex)) { return(false); } else if (shp.NumParts > 1) { // Shift up part indices if needed (bugzilla 798) bool shifting = false; for (int i = 0; i < shp.NumParts; i++) { if (shp.get_Part(i) >= insertIndex) { // Shift up this one and all remaining shifting = true; } if (shifting) { shp.set_Part(i, shp.get_Part(i) + 1); } } } m_Globals.CreateUndoPoint(); //stop editing and save changes shpFile.StopEditingShapes(true, true, null); return(true); } catch (System.Exception ex) { m_MapWin.ShowErrorDialog(ex); } return(false); }
/// <summary> /// If a Shape has multiple parts, this will create a separate polyline for each part. /// </summary> /// <param name="mwShape">A MapWinGIS.Shape that should be a LineString shape type</param> /// <returns>A List of Polylines derived from the various shapes</returns> public static List <LineString> mwShape_To_LineStrings(MapWinGIS.Shape mwShape) { if (Adapter.GetCategory(mwShape) != ShapeCategories.Line) { throw new ArgumentException("The Split method only takes Polyline shape types."); } List <LineString> newLines = new List <LineString>(); if (mwShape.NumParts <= 1) { LineString Part = new LineString(); for (int I = 0; I < mwShape.numPoints; I++) { Part.Add_Point(mwShape.get_Point(I)); } newLines.Add(Part); return(newLines); } int PartIndex = 0; for (int P = 0; P < mwShape.NumParts; P++) { LineString Part = new LineString(); int Pnext = mwShape.get_Part(P); for (int I = PartIndex; I < Pnext; I++) { Part.Add_Point(mwShape.get_Point(I)); } newLines.Add(Part); } return(newLines); }
/// <summary> /// This function scans a Polygon/PolygonM/PolygonZ to determine if any of the /// existing polygons are counter-clockwise. If they are, then it creates a linear ring /// from the shape. /// </summary> /// <param name="mwShape">A MapWinGIS.Shape Polygon/PolygonM/PolygonZ that might have holes.</param> /// <returns>A List of Linear Rings, each item representing one of the holes from the polygon.</returns> public static List <ILinearRing> GetHoles(MapWinGIS.Shape mwShape) { List <ILinearRing> Holes = new List <ILinearRing>(); MapWinGIS.Point mwPoint = new MapWinGIS.Point(); int pt = 0; int prt = 0; do { int Start = mwShape.get_Part(prt); int End; if (prt >= mwShape.NumParts - 1) { End = mwShape.numPoints; } else { End = mwShape.get_Part(prt + 1); } int Count = End - Start + 1; Coordinate[] Coords = new Coordinate[Count]; double area = 0; for (int PrtPoint = 0; PrtPoint < Count - 1; PrtPoint++) { // PrtPoint will be tracking the index for the specific linestring mwPoint = mwShape.get_Point(pt); Coords[PrtPoint] = new Coordinate(mwPoint.x, mwPoint.y); if (PrtPoint > 0) { area += Coords[PrtPoint].X * Coords[PrtPoint - 1].Y - Coords[PrtPoint - 1].X * Coords[PrtPoint].Y; } pt++; } mwPoint = mwShape.get_Point(Start); // close the loop Coords[Count - 1] = new Coordinate(mwPoint.x, mwPoint.y); area += Coords[Count - 2].X * Coords[Count - 1].Y - Coords[Count - 1].X * Coords[Count - 2].Y; // if the area is negative, then the shape is counter-clockwise and therefore a hole if (area < 0) { Holes.Add(new LinearRing(Coords)); } prt++; }while (prt < mwShape.NumParts); return(Holes); }
/// <summary> /// Returns a MultiLineString geometry collection derived from the mwShape /// </summary> /// <param name="mwShape">The shape to convert into a multi-line string</param> public static MultiLineString CreateMultiLineString(MapWinGIS.Shape mwShape) { MultiLineString MLS = new MultiLineString(); // Variables int numParts; // The number of parts in the shape int numPoints; // The number of points in the shape LineString LS; // Parameter checking if (mwShape == null) { throw new ArgumentException("mwShape should either not be null, or not be specified."); } if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINT || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTM || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTZ || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINT || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTM || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTZ) { throw new ArgumentException("Argument mwShape shapetype must be a polyline or polygon."); } MLS.GeometryN = new List <Geometry>(); numParts = mwShape.NumParts; numPoints = mwShape.numPoints; // if NumParts = 0, treat as though the whole shape was a single part int prt = 0; // prt is the part index int pt = 0; // pt is the point index while (prt < numParts - 1) { int maxpt = mwShape.get_Part(prt + 1); LS = new LineString(); while (pt < maxpt) { Coordinate Coord = GeometryFactory.CreateCoordinate(mwShape.get_Point(pt)); LS.Coordinates.Add(Coord); pt++; } MLS.GeometryN.Add(LS); prt++; } LS = new LineString(); while (pt < numPoints) { Coordinate Coord = GeometryFactory.CreateCoordinate(mwShape.get_Point(pt)); LS.Coordinates.Add(Coord); pt++; } MLS.GeometryN.Add(LS); return(MLS); }
private void ShiftDownVertices(ref MapWinGIS.Shape shp, int deleteIndex) { if (shp.NumParts > 1) { // Shift down part indices if needed (bugzilla 798) bool shifting = false; for (int i = 0; i < shp.NumParts; i++) { if (shp.get_Part(i) > deleteIndex) { // Shift up this one and all remaining shifting = true; } if (shifting) { shp.set_Part(i, Math.Max(0, shp.get_Part(i) - 1)); } } } }
/// <summary> /// Creates one multi-part polygon out of two input polygons. /// </summary> /// <param name="poly1">The first polygon to be combined.</param> /// <param name="poly2">The second polygon to be combined.</param> /// <param name="resultShp">The resulting multi-part polygon.</param> /// <returns>True if combining was successful, false otherwise.</returns> private static bool CombinePolygons(ref MapWinGIS.Shape poly1, ref MapWinGIS.Shape poly2, out MapWinGIS.Shape resultShp) { int p1NumParts = poly1.NumParts; if (p1NumParts == 0) { p1NumParts = 1; } int p2NumParts = poly2.NumParts; if (p2NumParts == 0) { p2NumParts = 1; } MapWinGIS.Shape multiShp = new MapWinGIS.ShapeClass(); multiShp.Create(poly1.ShapeType); int partIndex = 0; int pointIndex = 0; int numPoints = poly1.numPoints; int begPart = 0; int endPart = numPoints; //deal with the first shape and all of its parts // Globals.Vertex[][] p1VertArray = new Globals.Vertex[p1NumParts][]; // Globals.ConvertPolyToVertexArray(ref poly1, out p1VertArray); //bool firstIsClockwise = Globals.IsClockwise(ref p1VertArray[0]); for (int i = 0; i <= p1NumParts - 1; i++) { partIndex = i; pointIndex = multiShp.numPoints; multiShp.InsertPart(pointIndex, ref partIndex); begPart = poly1.get_Part(i); if (i < p1NumParts - 1) { endPart = poly1.get_Part(i + 1); } else { endPart = poly1.numPoints; } // if(firstIsClockwise) // { //add part for (int j = begPart; j <= endPart - 1; j++) { pointIndex = multiShp.numPoints; multiShp.InsertPoint(poly1.get_Point(j), ref pointIndex); } // } // else // { // //add part in reverse order // for(int j = endPart-1; j >= begPart; j--) // { // pointIndex = multiShp.numPoints; // multiShp.InsertPoint(poly1.get_Point(j), ref pointIndex); // } // } } //end of adding poly1 and all of its parts to the result shape //deal with the second shape and all of its parts // Globals.Vertex[][] p2VertArray = new Globals.Vertex[p2NumParts][]; // Globals.ConvertPolyToVertexArray(ref poly2, out p2VertArray); // bool secondIsClockwise = Globals.IsClockwise(ref p2VertArray[0]); partIndex++; numPoints = poly2.numPoints; begPart = 0; endPart = numPoints; for (int i = 0; i <= p2NumParts - 1; i++) { partIndex += i; pointIndex = multiShp.numPoints; multiShp.InsertPart(pointIndex, ref partIndex); begPart = poly2.get_Part(i); if (i < p2NumParts - 1) { endPart = poly2.get_Part(i + 1); } else { endPart = poly2.numPoints; } // if(secondIsClockwise) // { for (int j = begPart; j <= endPart - 1; j++) { pointIndex = multiShp.numPoints; multiShp.InsertPoint(poly2.get_Point(j), ref pointIndex); } // } // else // { // for(int j = endPart-1; j >= begPart; j--) // { // pointIndex = multiShp.numPoints; // multiShp.InsertPoint(poly2.get_Point(j), ref pointIndex); // } // } } //end of inserting parts from the second shape resultShp = multiShp; if (resultShp.numPoints > 0) { return(true); } else { gErrorMsg = "Error occured while trying to combine parts. No points in result shape."; Debug.WriteLine(gErrorMsg); Error.SetErrorMsg(gErrorMsg); MapWinUtility.Logger.Dbg(gErrorMsg); return(false); } }
/// <summary> /// calculate the area of large shapes in lat/long coordinates. /// The coordinates must be in decimal degrees /// the return value is in square kilometres /// </summary> /// <param name="shape">Polygon shape (decimal degree coordinates)</param> /// <returns>Area of the shape in square kilometres</returns> private static double SphericPolygonArea(ref MapWinGIS.Shape shape) { // added by Jiri Kadlec 3/16/2008 // // for each part of shape: // convert ellipsoid latitude to a latitude on equal-area unit sphere // convert the sphere coordinates from long/lat to x/y of sinusoidal equal-area projection // (x, y is in radians) // calculate area of the part // if it's a normal polygon, add it and if it's a hole, subtract it from total // area of shape // //note: this function uses the sphere approximation. It should be //used for large shapes with |max.latitude - min.latitude| > 1 degree. //please refer to: http://www.ucl.ac.uk/~ucessan/news/bob-aag2007.ppt // and: http://www.gmat.unsw.edu.au/wang/jgps/v5n12/v5n12p02.pdf //radius of equal-area sphere corresponding to WGS 84 ellipsoid double EARTH_RADIUS_SQUARED = Math.Pow(EqualAreaSphereRadius(), 2); //calculation modified from MapWinGeoProc.Statistics.Area double totalArea = 0.0; double indivArea = 0.0; int numParts = shape.NumParts; int numPoints = shape.numPoints; if (numParts > 1) //dealing with a multi-part polygon, hole areas must be subtracted from total { MapWinGIS.Shape[] allPolygons = new MapWinGIS.Shape[numParts]; int begPart; int endPart; for (int i = 0; i <= numParts - 1; i++) { allPolygons[i] = new MapWinGIS.ShapeClass(); allPolygons[i].ShapeType = shape.ShapeType; begPart = shape.get_Part(i); if (i < numParts - 1) { endPart = shape.get_Part(i + 1); } else { endPart = numPoints; } int ptIndex = 0; for (int j = begPart; j <= endPart - 1; j++) { allPolygons[i].InsertPoint(shape.get_Point(j), ref ptIndex); ptIndex++; }//end of creating separate polygons out of each part //calculate the area for each polygon part int numPolyPts = allPolygons[i].numPoints; indivArea = 0.0; for (int j = 0; j <= numPolyPts - 2; j++) { double oneY = EqualAreaSphereLat(Utils.deg2rad(allPolygons[i].get_Point(j).y)); double oneX = Utils.deg2rad(allPolygons[i].get_Point(j).x) * Math.Cos(oneY); double twoY = EqualAreaSphereLat(Utils.deg2rad(allPolygons[i].get_Point(j + 1).y)); double twoX = Utils.deg2rad(allPolygons[i].get_Point(j + 1).x) * Math.Cos(twoY); double trapArea = ((oneX * twoY) - (twoX * oneY)); indivArea += trapArea; } //end of calculating individual area for the current part totalArea += indivArea; } //end of looping through parts totalArea = 0.5 * Math.Abs(totalArea) * EARTH_RADIUS_SQUARED; } //end of dealing with multi-part polygons else { for (int j = 0; j <= numPoints - 2; j++) { double oneY = EqualAreaSphereLat(Utils.deg2rad(shape.get_Point(j).y)); double oneX = Utils.deg2rad(shape.get_Point(j).x) * Math.Cos(oneY); double twoY = EqualAreaSphereLat(Utils.deg2rad(shape.get_Point(j + 1).y)); double twoX = Utils.deg2rad(shape.get_Point(j + 1).x) * Math.Cos(twoY); double trapArea = ((oneX * twoY) - (twoX * oneY)); totalArea += trapArea; } totalArea = 0.5 * Math.Abs(totalArea) * EARTH_RADIUS_SQUARED; } return(totalArea); }
//see: http://astronomy.swin.edu.au/~pbourke/geometry/polyarea/ //for a simple explanation on how to calculate the area of a polygon. // 16. Mar 2008 modified by Jiri Kadlec for shapes in lat/long coordinates. /// <summary> /// Computes the area of a polygon. For multi-part polygons, assume holes are counter-clockwise. /// To calculate the area correctly, the shape must have an equal-area projection. For shapes /// in Lat/Long coordinates use the LLArea() function. /// </summary> /// <param name="shape">The polygon shape.</param> /// <returns>The area in square units, or 0.0 if it could not be found.</returns> public static double Area(ref MapWinGIS.Shape shape) { Error.ClearErrorLog(); double area; if (shape == null) { area = 0.0; gErrorMsg = "Unexpected null paramter: shape."; Error.SetErrorMsg(gErrorMsg); Debug.WriteLine(gErrorMsg); return(area); } MapWinGIS.ShpfileType shpType; shpType = shape.ShapeType; if (shpType != MapWinGIS.ShpfileType.SHP_POLYGON && shpType != MapWinGIS.ShpfileType.SHP_POLYGONM && shpType != MapWinGIS.ShpfileType.SHP_POLYGONZ) { area = 0.0; gErrorMsg = "Incompatible shape type: must be of type polygon in order to calculate area."; Error.SetErrorMsg(gErrorMsg); Debug.WriteLine(gErrorMsg); return(area); } double totalArea = 0.0; double indivArea = 0.0; int numParts = shape.NumParts; int numPoints = shape.numPoints; if (numParts > 1) //dealing with a multi-part polygon, hole areas must be subtracted from total { MapWinGIS.Shape[] allPolygons = new MapWinGIS.Shape[numParts]; int begPart; int endPart; for (int i = 0; i <= numParts - 1; i++) { allPolygons[i] = new MapWinGIS.ShapeClass(); allPolygons[i].ShapeType = shpType; begPart = shape.get_Part(i); if (i < numParts - 1) { endPart = shape.get_Part(i + 1); } else { endPart = numPoints; } int ptIndex = 0; for (int j = begPart; j <= endPart - 1; j++) { allPolygons[i].InsertPoint(shape.get_Point(j), ref ptIndex); ptIndex++; } //end of creating separate polygons out of each part //calculate the area for each polygon part int numPolyPts = allPolygons[i].numPoints; indivArea = 0.0; for (int j = 0; j <= numPolyPts - 2; j++) { double oneX = allPolygons[i].get_Point(j).x; double oneY = allPolygons[i].get_Point(j).y; double twoX = allPolygons[i].get_Point(j + 1).x; double twoY = allPolygons[i].get_Point(j + 1).y; double trapArea = ((oneX * twoY) - (twoX * oneY)); indivArea += trapArea; } //end of calculating individual area for the current part totalArea += indivArea; } //end of looping through parts totalArea = 0.5 * Math.Abs(totalArea); } //end of dealing with multi-part polygons else { for (int i = 0; i <= numPoints - 2; i++) { double oneX = shape.get_Point(i).x; double oneY = shape.get_Point(i).y; double twoX = shape.get_Point(i + 1).x; double twoY = shape.get_Point(i + 1).y; double trapArea = ((oneX * twoY) - (twoX * oneY)); totalArea += trapArea; } totalArea = 0.5 * Math.Abs(totalArea); } return(totalArea); }
private void btnOK_Click(object sender, EventArgs e) { double tolerance = 0; if (!double.TryParse(txtTolerance.Text, out tolerance)) { MapWinUtility.Logger.Message("Please enter only numbers in the distance field.", "Enter Only Numbers", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, DialogResult.OK); return; } this.Cursor = Cursors.WaitCursor; prgShape.Visible = true; prgPoint.Visible = true; sf.StartEditingShapes(true, null); long totalRemoved = 0; long fromShapes = 0; int numPts; System.Collections.ArrayList removeList = new System.Collections.ArrayList(); if (sf.NumShapes > 0) { prgShape.Maximum = sf.NumShapes; for (int z = 0; z < sf.NumShapes; z++) { MapWinGIS.Shape shp = sf.get_Shape(z); if (z < 100 || z % 5 == 0) { prgShape.Value = z; this.Refresh(); } Application.DoEvents(); numPts = shp.numPoints; if (numPts > 0) { prgPoint.Maximum = numPts; for (int i = numPts - 1; i > 0; i--) // 0 never needs to actually be hit, inner loop will compare against all zeros { if (i % 5 == 0) { prgPoint.Value = numPts - i; this.Refresh(); } for (int j = i - 1; j >= 0; j--) { if (Math.Sqrt(Math.Pow(shp.get_Point(i).x - shp.get_Point(j).x, 2) + Math.Pow(shp.get_Point(i).y - shp.get_Point(j).y, 2)) < tolerance) { // Make sure that !(i == numPts - 1 && j == 0) -- polygon completion point if (!removeList.Contains(i) && !(i == numPts - 1 && j == 0)) { removeList.Add(i); } } } } } if (removeList.Count > 0) { if (removeList.Count >= shp.numPoints - 1) { // Probably not a good thing..... MapWinUtility.Logger.Message("Aborting: Proceeding will remove all points from one or more shapes. The distance may need to be smaller, particularly for unprojected (latitute and longitude) coordinate systems.", "Aborting -- All Points Would Be Removed", MessageBoxButtons.OK, MessageBoxIcon.Error, DialogResult.OK); sf.StopEditingShapes(false, true, null); this.Cursor = Cursors.Default; prgPoint.Value = 0; prgShape.Value = 0; prgPoint.Visible = false; prgShape.Visible = false; this.Cursor = Cursors.Default; return; } totalRemoved += removeList.Count; fromShapes++; while (removeList.Count > 0) { for (int part = 0; part < shp.NumParts; part++) { if (shp.get_Part(part) >= (int)removeList[0]) { shp.set_Part(part, shp.get_Part(part) - 1); } } shp.DeletePoint((int)removeList[0]); removeList.RemoveAt(0); } // If this is a polygon and there are now less than 3 shapes, panic if ((shp.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGON || shp.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONZ || shp.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONM) && shp.numPoints < 3) { // Probably not a good thing..... MapWinUtility.Logger.Message("Aborting: Proceeding will leave less than 3 points in a polygon. The distance may need to be smaller, particularly for unprojected (latitute and longitude) coordinate systems.", "Aborting -- Polygons Would Be Destroyed", MessageBoxButtons.OK, MessageBoxIcon.Error, DialogResult.OK); sf.StopEditingShapes(false, true, null); this.Cursor = Cursors.Default; prgPoint.Value = 0; prgShape.Value = 0; prgPoint.Visible = false; prgShape.Visible = false; this.Cursor = Cursors.Default; return; } // If the first and last points are not the same now, reclose it if (shp.get_Point(0).x != shp.get_Point(shp.numPoints - 1).x || shp.get_Point(0).y != shp.get_Point(shp.numPoints - 1).y) { MapWinGIS.Point pnt = new MapWinGIS.Point(); pnt.x = shp.get_Point(0).x; pnt.y = shp.get_Point(0).y; pnt.Z = shp.get_Point(0).Z; int ptidx = shp.numPoints; shp.InsertPoint(pnt, ref ptidx); } } } } prgPoint.Value = prgPoint.Maximum; prgShape.Value = prgShape.Maximum; g.CreateUndoPoint(); sf.StopEditingShapes(true, true, null); this.Cursor = Cursors.Default; if (totalRemoved > 0) { MapWinUtility.Logger.Message("There were " + totalRemoved.ToString() + " points removed from " + fromShapes.ToString() + " shapes.", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Information, DialogResult.OK); } else { MapWinUtility.Logger.Message("Finished -- no extra points needed to be removed.", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Information, DialogResult.OK); } this.DialogResult = DialogResult.OK; this.Close(); }
/// <summary> /// Converts a MapWinGIS.Shape of any type to the associated geometry. /// Clockwise/Counter clockwise arrangements are important for polygons. /// Any hole that isn't correctly counter-clockwise will be treated as a polygon. /// Any clockwise "hole" that is not contained by at least one polygon will be /// reversed to clockwise and returned as a polygon. /// NULLSHAPE || MULTIPATCH --> throws exception. /// POINT || POINTM || POINTZ --> Geometries.Point /// MULTIPOINT || MULTIPOINTM || MULTIPOINTZ --> Geometries.MultiPoint /// {1 part} POLYLINE || POLYLINEM || POLYLINEZ --> Geometires.LineString /// {n parts} POLYLINE || POLYLINEM || POLYLINEZ --> Geometires.MultiLineString /// {1 shell} POLYGON || POLYGONM || POLYGONZ --> Geometires.Polygon /// {n shells} POLYGON || POLYGONM || POLYGONZ --> Geometries.MultiPolygon /// </summary> /// <param name="mwShape">A MapWinGIS.Shape to convert to a Geometry</param> /// <returns>Geometry representing the shape specified by mwShape.</returns> /// public static Geometry ShapeToGeometry(MapWinGIS.Shape mwShape) { #region -------------------------- UNSUPPORTED ------------------------------------- MapWinGIS.Point mwPoint; // a generic MapWinGIS style point // ------------ NOT SUPPORTED if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH) { throw new ArgumentException("Shape type is not supported."); } #endregion #region -------------------------- POINT ------------------------------------------- // ------------- POINT if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINT || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTM || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POINTZ) { // The shape represents a single point, so return a single point Coordinate Coord = new Coordinate(mwShape.get_Point(0).x, mwShape.get_Point(0).y); return(new Point(Coord)); } #endregion #region -------------------------- MULTI POINT ------------------------------------- if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINT || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTM || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPOINTZ) { Point[] Coords = new Point[mwShape.numPoints]; for (int pt = 0; pt < mwShape.numPoints; pt++) { mwPoint = mwShape.get_Point(pt); Coords[pt] = new Point(mwPoint.x, mwPoint.y); } return(new MultiPoint(Coords)); } #endregion #region -------------------------- LINE STRINGS ------------------------------------ if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINE || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEM || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYLINEZ) { // ------------- LINE STRING if (mwShape.NumParts < 2) { Coordinate[] Coords = new Coordinate[mwShape.numPoints]; for (int pt = 0; pt < mwShape.numPoints; pt++) { mwPoint = mwShape.get_Point(pt); Coords[pt] = new Coordinate(mwPoint.x, mwPoint.y); } return(new LineString(Coords)); } // ------------- MULTI LINE STRING else { int pt = 0; LineString[] Lines = new LineString[mwShape.NumParts]; for (int prt = 0; prt < mwShape.NumParts; prt++) { int Start = mwShape.get_Part(prt); int End; if (prt == mwShape.NumParts - 1) { End = mwShape.numPoints; } else { End = mwShape.get_Part(prt + 1); } Coordinate[] Coords = new Coordinate[End - Start]; for (int PrtPoint = 0; PrtPoint < End - Start; PrtPoint++) { // PrtPoint will be tracking the index for the specific linestring mwPoint = mwShape.get_Point(pt); Coords[PrtPoint] = new Coordinate(mwPoint.x, mwPoint.y); pt++; } // Create a new linestring using only the coordinates for a specific part Lines[prt] = new LineString(Coords); } return(new MultiLineString(Lines)); } } #endregion #region -------------------------- POLYGONS ---------------------------------------- if (mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGON || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONM || mwShape.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONZ) { // Polygons are complex and not as straight forward as linear rings. // A multi-part shape might just be a single polygon with a hole. List <NRings> Rings = new List <NRings>(); List <LinearRing> Holes = new List <LinearRing>(); int pt = 0; int prt = 0; List <LinearRing> RawRings = new List <LinearRing>(); do { int Start = mwShape.get_Part(prt); int End; if (prt >= mwShape.NumParts - 1) { End = mwShape.numPoints; } else { End = mwShape.get_Part(prt + 1); } int Count = End - Start + 1; Coordinate[] Coords = new Coordinate[Count]; double area = 0; for (int PrtPoint = 0; PrtPoint < Count - 1; PrtPoint++) { // PrtPoint will be tracking the index for the specific linestring mwPoint = mwShape.get_Point(pt); Coords[PrtPoint] = new Coordinate(mwPoint.x, mwPoint.y); if (PrtPoint > 0) { area += Coords[PrtPoint].X * Coords[PrtPoint - 1].Y - Coords[PrtPoint - 1].X * Coords[PrtPoint].Y; } pt++; } mwPoint = mwShape.get_Point(Start); // close the loop Coords[Count - 1] = new Coordinate(mwPoint.x, mwPoint.y); area += Coords[Count - 2].X * Coords[Count - 1].Y - Coords[Count - 1].X * Coords[Count - 2].Y; // if the area is negative, then the shape is counter-clockwise and therefore a hole if (area < 0) { Holes.Add(new LinearRing(Coords)); } else { Rings.Add(new NRings(Coords)); } prt++; } while (prt < mwShape.NumParts); // Add the holes to every ring that can hold it. for (int iHole = 0; iHole < Holes.Count; iHole++) { bool HolePunched = false; for (int iRing = 0; iRing < Rings.Count; iRing++) { if (Rings[iRing].Ring.Contains(Holes[iHole])) { Rings[iRing].Holes.Add(Holes[iHole]); HolePunched = true; } } // If we couldn't punch the hole anywhere, then we will turn it into a polygon if (HolePunched == false) { ILineString LS = Holes[iHole].Reverse(); //Switch to clockwise Rings.Add(new NRings(LS.Coordinates)); } } // Create polygons from each of the rings and add them to a multipolygon if (Rings.Count == 1) { if (Rings[0].Holes.Count > 0) { LinearRing[] HoleArray = new LinearRing[Rings[0].Holes.Count]; for (int iHole = 0; iHole < Rings[0].Holes.Count; iHole++) { HoleArray[iHole] = Rings[0].Holes[iHole]; } return(new Polygon(Rings[0].Ring, HoleArray)); } else { return(new Polygon(Rings[0].Ring)); } } Polygon[] Polygons = new Polygon[Rings.Count]; for (int iRing = 0; iRing < Rings.Count; iRing++) { if (Rings[iRing].Holes.Count > 0) { LinearRing[] HoleArray = new LinearRing[Rings[iRing].Holes.Count]; for (int iHole = 0; iHole < Rings[iRing].Holes.Count; iHole++) { HoleArray[iHole] = Rings[0].Holes[iHole]; } Polygons[iRing] = new Polygon(Rings[iRing].Ring, HoleArray); } else { Polygons[iRing] = new Polygon(Rings[iRing].Ring); } } return(new MultiPolygon(Polygons)); } #endregion // There shouldn't be any way to get here. throw new ApplicationException("The shapetype specified is invalid, or new and not handled yet."); }