/// <summary> /// Not Implemented /// This function will calculate the length of every line shape in the shapefile and save the results to the corresponding .dbf table. /// </summary> /// <param name="sf">The shapefile of lines whose lengths are to be computed.</param> /// <param name="fieldIndex">The field index of the field to update with values.</param> /// <param name="Units">The units of the dataset (e.g., Meters, Lat/Long).</param> /// <returns>False if an error was encountered, true otherwise.</returns> public static bool ComputeLengths(MapWinGIS.Shapefile sf, int fieldIndex, string Units) { try { //Loop trough all shapes for (int i = 0; i <= sf.NumShapes - 1; i++) { double length = 0f; MapWinGIS.Shape line = new MapWinGIS.Shape(); //Measure length of each line part line = sf.get_Shape(i); //-2 else out of bounds!! for (int j = 0; j <= line.numPoints - 2; j++) { length += DistancePointToPoint(line.get_Point(j).x, line.get_Point(j).y, line.get_Point(j + 1).x, line.get_Point(j + 1).y, Units); } //Add length as attribute: if (!sf.EditCellValue(fieldIndex, i, length)) { Error.SetErrorMsg(sf.get_ErrorMsg(sf.LastErrorCode)); } } return(false); } catch (Exception lEx) { Error.SetErrorMsg(lEx.ToString()); return(false); } }
private void ShrinkOrGrowPoly(ref MapWinGIS.Shape shp, double distance) { MapWinGIS.Point centroid = MapWinGeoProc.Statistics.Centroid(ref shp); // Avoid OLE calls; cache centroid point in local variable double cx = centroid.x; double cy = centroid.y; for (int i = 0; i < shp.numPoints; i++) { double ox = shp.get_Point(i).x; double oy = shp.get_Point(i).y; // Find the adjusted "real" distance (rdistance) double rdistance = Math.Sqrt(Math.Pow(cy - oy, 2) + Math.Pow(cx - ox, 2)) + distance; // Find the full distance of point to centroid (fdistance) double fdistance = Math.Sqrt(Math.Pow(cy - oy, 2) + Math.Pow(cx - ox, 2)); if (rdistance < 0.00001) { MapWinUtility.Logger.Message("Shrinking the shape by this amount will result in losing some shape geometry; aborting.", "Aborting - Loss of Geometry", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, DialogResult.OK); return; } // Find the new point (project the old point along the line from point to midpoint) shp.get_Point(i).x = cx + (rdistance / fdistance) * (ox - cx); shp.get_Point(i).y = cy + (rdistance / fdistance) * (oy - cy); } }
/// <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); }
private void DrawMoveLine(double x, double y, System.Collections.ArrayList snapPoints) { try { if (snapPoints.Count == 0) { return; } double projX = 0, projY = 0; m_MapWin.View.PixelToProj(x, y, ref projX, ref projY); //get the working shapefile if (m_globals.CurrentLayer == null) { return; } MapWinGIS.Shapefile shpFile = m_globals.CurrentLayer; //get the current vertex index ShapefileEditor.SnapData snapData = (ShapefileEditor.SnapData)snapPoints[0]; int vertexIndex = snapData.pointIndex; //get the current shape MapWinGIS.Shape shp = shpFile.get_Shape(snapData.shpIndex); if (shpFile.ShapefileType == MapWinGIS.ShpfileType.SHP_POINT) { m_MapWin.View.Draw.DrawPoint(projX, projY, m_globals.VertexSize, System.Drawing.Color.Red); } else { if (vertexIndex > 0 && vertexIndex < shp.numPoints - 1) { //draw a line from the prev to current to next vertex MapWinGIS.Point prevPoint = shp.get_Point(vertexIndex - 1); MapWinGIS.Point nextPoint = shp.get_Point(vertexIndex + 1); m_MapWin.View.Draw.DrawLine(prevPoint.x, prevPoint.y, projX, projY, 2, System.Drawing.Color.Red); m_MapWin.View.Draw.DrawLine(projX, projY, nextPoint.x, nextPoint.y, 2, System.Drawing.Color.Red); } else if (vertexIndex == 0) { MapWinGIS.Point nextPoint = shp.get_Point(vertexIndex + 1); m_MapWin.View.Draw.DrawLine(projX, projY, nextPoint.x, nextPoint.y, 2, System.Drawing.Color.Red); } else if (vertexIndex == shp.numPoints - 1) { MapWinGIS.Point prevPoint = shp.get_Point(vertexIndex - 1); m_MapWin.View.Draw.DrawLine(prevPoint.x, prevPoint.y, projX, projY, 2, System.Drawing.Color.Red); } } } catch (System.Exception ex) { m_MapWin.ShowErrorDialog(ex); } }
/// <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); }
// Returns only the point index values of the shapes in the interesection of the shape extents private static void PointsOfInterest(MapWinGIS.Shape Shape1, MapWinGIS.Shape Shape2, ref List <int> Points1, ref List <int> Points2) { Envelope Rect1, Rect2, rectIntersect; Rect1 = new Envelope(Shape1.Extents); Rect2 = new Envelope(Shape2.Extents); rectIntersect = (Envelope)Rect1.Intersection(Rect2); MapWinGIS.Point pt = new MapWinGIS.Point(); // reduce our points to points of interrest int numPoints1 = Shape1.numPoints; for (int I = 0; I < numPoints1; I++) { pt = Shape1.get_Point(I); if (rectIntersect.Intersects(pt)) { Points1.Add(I); } } int numPoints2 = Shape2.numPoints; for (int I = 0; I < numPoints2; I++) { pt = Shape2.get_Point(I); if (rectIntersect.Intersects(pt)) { Points2.Add(I); } } }
private void MarkAllVertices() { try { MapWinGIS.Shape shp = null; MapWinGIS.Shapefile sf = m_globals.CurrentLayer; MapWindow.Interfaces.View v = m_globals.MapWin.View; //clear the drawings v.Draw.ClearDrawing(m_HDraw); m_HDraw = v.Draw.NewDrawing(MapWinGIS.tkDrawReferenceList.dlSpatiallyReferencedList); //display all the vertices for each shape for (int i = 0; i < v.SelectedShapes.NumSelected; i++) { shp = sf.get_Shape(v.SelectedShapes[i].ShapeIndex); for (int j = 0; j < shp.numPoints; j++) { MapWinGIS.Point shpPoint = shp.get_Point(j); m_globals.MapWin.View.Draw.DrawPoint(shpPoint.x, shpPoint.y, m_globals.VertexSize, System.Drawing.Color.Red); } } } catch (System.Exception ex) { m_globals.MapWin.ShowErrorDialog(ex); } }
/// <summary> /// Creates a new instance of the polyline class /// </summary> /// <param name="mwShape">A MapWinGIS.Shape to derive the polyline from</param> /// <remarks>Assumes shape is one part. To Split Multipart shapes, use Split.</remarks> public LineString(MapWinGIS.Shape mwShape) { if (Adapter.GetCategory(mwShape) != ShapeCategories.Line) { throw new ArgumentException("The Split method only takes Polyline shape types."); } m_Envelope = new Envelope(mwShape.Extents); extentsValid = true; // When adding all the points at once, we have no problem. m_Length = 0; lengthValid = false; // Calculate this only if it is needed m_Center = new Point((m_Envelope.xMin + m_Envelope.xMax) / 2, (m_Envelope.yMin + m_Envelope.yMax) / 2, (m_Envelope.zMin + m_Envelope.zMax) / 2); centerValid = true; // since extents were ok already, we can quickly find the center m_MaxRadius = 0; maxradiusValid = false; // Calculate this only if it is needed m_Points = new List <Point>(); for (int I = 0; I < mwShape.NumParts; I++) { Add_Point(mwShape.get_Point(I)); } }
/// <summary> /// Creates a new instance of the Polygon class /// The shape is closed, but the first and last point will be the same. /// This way, algorithms don't have to loop back to the 0 point in order to evaluate /// the final segment. /// </summary> /// <param name="mwShape">A MapWinGIS.Shape to derive the Polygon from</param> /// <remarks>Assumes shape is one part. To Split Multipart shapes, use Split.</remarks> public Polygon(MapWinGIS.Shape mwShape) { if (Adapter.GetCategory(mwShape) != ShapeCategories.Polygon) { throw new ArgumentException("The Split method only takes Polygon shape types."); } m_Area = 0; areaValid = false; // Calculate this when needed and then cache it. m_Envelope = new Envelope(mwShape.Extents); extentsValid = true; // When adding all the points at once, we have no problem. m_Center = new Point((m_Envelope.xMin + m_Envelope.xMax) / 2, (m_Envelope.yMin + m_Envelope.yMax) / 2, (m_Envelope.zMin + m_Envelope.zMax) / 2); centerValid = true; // since extents were ok already, we can quickly find the center m_Perimeter = 0.0; perimeterValid = false; // Calculate this only if it is needed m_MaxRadius = 0.0; maxradiusValid = false; // Calculate this only if it is needed m_Points = new List <Point>(); // skip the last duplicate point for (int I = 0; I < mwShape.NumParts - 1; I++) { Add_Point(mwShape.get_Point(I)); } }
/// <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); }
private void RotateShape(MapWinGIS.Shape shape, double Angle, double aboutX, double aboutY) { for (int i = 0; i < shape.numPoints; i++) { MapWinGIS.Point pt = shape.get_Point(i); double Nx = 0, Ny = 0; Rotate(Angle, pt.x, pt.y, aboutX, aboutY, ref Nx, ref Ny); pt.x = Nx; pt.y = Ny; } }
/// <summary> /// Finds the points within extents for polygons and polylines and automatically creates a list /// of appropriate line segments representing all the segments found within the extents. /// </summary> /// <param name="LineOrPolygon">A MapWinGIS.Shape that is a line or polygon shape</param> /// <param name="Rect">A Envelope defining the region of interrest</param> /// <returns>A list of all segments that have at least one point within or on the extents</returns> public static List <LineSegment> LineSegmentsWithinRect(MapWinGIS.Shape LineOrPolygon, Envelope Rect) { List <LineSegment> ContainedLineSegments = new List <LineSegment>(); ShapeCategories Category = GetCategory(LineOrPolygon); if (LineOrPolygon == null) { throw new ArgumentException("Argument for Line or Polygon cannot be null"); } if (Category != ShapeCategories.Polygon && Category != ShapeCategories.Line) { throw new ArgumentException("The input argument must be a line or polygon or else it doesn't have segments."); } Envelope rectShape, rectIntersect; rectShape = new Envelope(LineOrPolygon.Extents); rectIntersect = (Envelope)rectShape.Intersection(Rect); int numPoints = LineOrPolygon.numPoints; bool PreviousPointIncluded = true; // the first and last points are the same, so don't look backwards from point 1 for (int I = 0; I < numPoints - 1; I++) { MapWinGIS.Point pt = LineOrPolygon.get_Point(I); if (rectIntersect.Intersects(pt)) { if (PreviousPointIncluded == false) { ContainedLineSegments.Add(new LineSegment(LineOrPolygon.get_Point(I - 1), pt)); } // since this point is contained, we know for sure that we need the next segment ContainedLineSegments.Add(new LineSegment(LineOrPolygon.get_Point(I), LineOrPolygon.get_Point(I + 1))); PreviousPointIncluded = true; } else { PreviousPointIncluded = false; } } return(ContainedLineSegments); }
/// <summary> /// Creates a new instance of the polyline class /// </summary> /// <param name="MapWinGIS_Shape">A MapWinGIS.Shape to derive the polyline from</param> /// <remarks>Assumes shape is one part. To Split Multipart shapes, use Split.</remarks> public static LineString CreateLineString(object MapWinGIS_Shape) { if (MapWinGIS_Shape.GetType() != typeof(MapWinGIS.ShapeClass)) { return(null); } MapWinGIS.Shape mwShape = MapWinGIS_Shape as MapWinGIS.Shape; LineString LS = new LineString(); LS.Envelope = new Envelope(mwShape.Extents); LS.Coordinates = new List <Coordinate>(); for (int I = 0; I < mwShape.numPoints; I++) { MapWinGIS.Point mwPoint = mwShape.get_Point(I); LS.Coordinates.Add(new Coordinate(mwPoint.x, mwPoint.y)); } return(LS); }
/// <summary> /// Finds a list of point indecies from a MapWinGIS.Shape that are within the rectangle specified /// </summary> /// <param name="Shape">A mapWinGIS.Shape object to select points from</param> /// <param name="Rect">A Envelope structure representing a rectangle to search</param> /// <returns>A List of integer values representing the index values of the points within the rectangle</returns> public static List <int> PointsWithinRect(MapWinGIS.Shape Shape, Envelope Rect) { List <int> ContainedPoints = new List <int>(); Envelope RectShape, rectIntersect; RectShape = new Envelope(Shape.Extents); rectIntersect = (Envelope)RectShape.Intersection(Rect); MapWinGIS.Point pt = new MapWinGIS.Point(); int numPoints = Shape.numPoints; for (int I = 0; I < numPoints; I++) { pt = Shape.get_Point(I); if (rectIntersect.Intersects(pt)) { ContainedPoints.Add(I); } } return(ContainedPoints); }
// Only returns true if a point from shape1 is the same location as shape2 private static bool MultiPoints_TouchTheBoundaryOf(MapWinGIS.Shape Shape1, MapWinGIS.Shape Shape2) { List <int> Points1 = new List <int>(); // Points from Shape1 where the rectangular shape extents overlap List <int> Points2 = new List <int>(); // Points from Shape2 where the rectangular shape extents overlap MapWinGIS.Point pt1, pt2; PointsOfInterest(Shape1, Shape2, ref Points1, ref Points2); for (int I = 0; I < Points1.Count; I++) { for (int J = 0; J < Points2.Count; J++) { pt1 = Shape1.get_Point(Points1[I]); pt2 = Shape2.get_Point(Points2[J]); if (pt1.x == pt2.x && pt1.y == pt2.y) { return(true); } } } return(false); }
private void MoveYOverDistance(MapWinGIS.Shape objShape, int ixPoint, double dblDistance, double dblSgn) { objShape.get_Point(ixPoint).y = objShape.get_Point(ixPoint).y + dblSgn * dblDistance; }
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> /// 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> /// Erases the portions of the polygon shapefile that are within the polygon shape. /// </summary> /// <param name="polySF">The polygon shapefile.</param> /// <param name="polygon">The erase polygon.</param> /// <param name="resultSF">The resulting shapefile, with portions removed.</param> /// <param name="CopyAttributes">Indicates whether to copy attributes or not.</param> /// <returns>False if an error was encountered, true otherwise.</returns> public static bool ErasePolySFWithPoly(ref MapWinGIS.Shapefile polySF, ref MapWinGIS.Shape polygon, ref MapWinGIS.Shapefile resultSF, bool CopyAttributes) { MapWinUtility.Logger.Dbg("ErasePolySFWithPoly(polySF: " + Macro.ParamName(polySF) + ",\n" + " polygon: " + Macro.ParamName(polygon) + ",\n" + " resultSF: " + Macro.ParamName(resultSF) + "\n" + " CopyAttributes: " + CopyAttributes.ToString()); if (polySF == null || polygon == null || resultSF == null) { gErrorMsg = "One of the input parameters is null."; Error.SetErrorMsg(gErrorMsg); Debug.WriteLine(gErrorMsg); MapWinUtility.Logger.Dbg(gErrorMsg); return(false); } if (CopyAttributes) { string tmpName; MapWinGIS.Field tmpField, currField; for (int f = 0; f <= polySF.NumFields - 1; f++) { tmpField = new MapWinGIS.Field(); currField = polySF.get_Field(f); tmpName = currField.Name; tmpField.Name = tmpName; tmpField.Width = currField.Width; tmpField.Type = currField.Type; tmpField.Precision = currField.Precision; tmpField.Key = currField.Key; resultSF.EditInsertField(tmpField, ref f, null); } } int numShapes = polySF.NumShapes; int shpIndex = 0; for (int i = 0; i <= numShapes - 1; i++) { MapWinGIS.Shape currShape = new MapWinGIS.Shape(); MapWinGIS.Shape resultShp = new MapWinGIS.Shape(); currShape = polySF.get_Shape(i); //if bounds intersect, then check if all polygon points are inside the currShape if (Globals.CheckBounds(ref currShape, ref polygon)) { int numPts = polygon.numPoints; bool allInside = true; int numParts = currShape.NumParts; if (numParts == 0) { numParts = 1; } Globals.Vertex[][] vertArray = new Globals.Vertex[numParts][]; Globals.ConvertPolyToVertexArray(ref currShape, out vertArray); for (int j = 0; j <= numPts - 1; j++) { double x = polygon.get_Point(j).x; double y = polygon.get_Point(j).y; if (Utils.PointInPoly(ref vertArray, x, y) == false) { allInside = false; break; } } if (allInside == true) { resultShp = new MapWinGIS.ShapeClass(); resultShp.Create(polygon.ShapeType); //we want the symmetric difference of these two shapes //which should leave us with a hole where the erase polygon was in the currShape resultShp = SpatialOperations.SymmetricDifference(polygon, currShape); } else { //erase overlapping section and add result to the file. MapWinGIS.Shape intersect = new MapWinGIS.ShapeClass(); intersect.ShapeType = polygon.ShapeType; intersect = SpatialOperations.Intersection(polygon, currShape); if (intersect.numPoints > 0) { //there might be parts in the difference result that do not belong, //perform an intersection operation with currShape to remove them. MapWinGIS.Shape diff = new MapWinGIS.ShapeClass(); diff.ShapeType = polygon.ShapeType; //diff = SpatialOperations.SymmetricDifference(intersect, currShape); diff = SpatialOperations.Difference(currShape, polygon); int numPoints = diff.numPoints; if (numPoints > 0) { resultShp = diff; } //difference operation successful } //intersect operation successful else { //no intersection, shapes do not collide resultShp = currShape; } } //all points of erase polygon are not inside currShape if (resultShp.numPoints > 0) { shpIndex = resultSF.NumShapes; if (resultSF.EditInsertShape(resultShp, ref shpIndex) == false) { gErrorMsg = "ErasePolySF: problem inserting shape into result file: " + resultSF.get_ErrorMsg(resultSF.LastErrorCode); Debug.WriteLine(gErrorMsg); Error.SetErrorMsg(gErrorMsg); MapWinUtility.Logger.Dbg(gErrorMsg); return(false); } if (CopyAttributes) { for (int f = 0; f <= polySF.NumFields - 1; f++) { bool tmpbool = resultSF.EditCellValue(f, shpIndex, polySF.get_CellValue(f, i)); } } } } //end of if bounds intersect else { //the erase object does not intersect with the current polygon, //add current polygon to resultSF in unchanged form shpIndex = resultSF.NumShapes; if (resultSF.EditInsertShape(currShape, ref shpIndex) == false) { gErrorMsg = "ErasePolySF: problem inserting shape into result file: " + resultSF.get_ErrorMsg(resultSF.LastErrorCode); Debug.WriteLine(gErrorMsg); Error.SetErrorMsg(gErrorMsg); MapWinUtility.Logger.Dbg(gErrorMsg); return(false); } if (CopyAttributes) { for (int f = 0; f <= polySF.NumFields - 1; f++) { bool tmpbool = resultSF.EditCellValue(f, shpIndex, polySF.get_CellValue(f, i)); } } } } //end of looping through shapes in shapefile MapWinUtility.Logger.Dbg("Finished ErasePolySFWithPoly"); return(true); }
/// <summary> /// Checks whether the borders of a polygon shape, lines of line shapes, or points of point shapes touch. /// </summary> /// <param name="Shape1">A MapWinGIS.Shape object to test</param> /// <param name="Shape2">A MapWinGIS.Shape object to test</param> /// <returns>True if the boundaries touch</returns> public static bool ShapeBoundariesTouch(MapWinGIS.Shape Shape1, MapWinGIS.Shape Shape2) { if (Shape1 == null || Shape1.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE) { throw new ArgumentException("Argument Shape1 cannot be null"); } if (Shape2 == null || Shape2.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE) { throw new ArgumentException("Argument Shape2 cannot be null"); } if (Shape1.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH) { throw new ArgumentException("Multipatch is not supported"); } if (Shape2.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH) { throw new ArgumentException("Multipatch is not supported"); } ShapeCategories Typ1, Typ2; Typ1 = GetCategory(Shape1); Typ2 = GetCategory(Shape2); // for single points, simply show if these specific points overlap if (Typ1 == ShapeCategories.Point && Typ2 == ShapeCategories.Point) { Point p1 = new Point(Shape1.get_Point(0)); Point p2 = new Point(Shape2.get_Point(0)); if (p1.Intersects(p2)) { return(true); } return(false); } // Point to Non-point if (Typ1 == ShapeCategories.Point) { Point p1 = new Point(Shape1.get_Point(0)); if (Typ2 == ShapeCategories.MultiPoint) { for (int I = 0; I < Shape2.numPoints; I++) { Point p2 = new Point(Shape2.get_Point(I)); if (p1.Intersects(p2)) { return(true); } } return(false); } else { for (int I = 0; I < Shape2.numPoints - 1; I++) { LineSegment seg = new LineSegment(Shape2.get_Point(I), Shape2.get_Point(I + 1)); if (seg.Intersects(p1)) { return(true); } } return(false); } } // Point2 to non-point if (Typ2 == ShapeCategories.Point) { Point p2 = new Point(Shape2.get_Point(0)); if (Typ1 == ShapeCategories.MultiPoint) { for (int I = 0; I < Shape1.numPoints; I++) { Point p1 = new Point(Shape1.get_Point(I)); if (p2.Intersects(p1)) { return(true); } } return(false); } else { for (int I = 0; I < Shape1.numPoints - 1; I++) { LineSegment seg = new LineSegment(Shape1.get_Point(I), Shape1.get_Point(I + 1)); if (seg.Intersects(p2)) { return(true); } } return(false); } } // for multipoint, test every point for intersection. if (Typ1 == ShapeCategories.MultiPoint && Typ2 == ShapeCategories.MultiPoint) { List <int> Points1 = PointsWithinEnvelope(Shape1, Shape2.Extents); List <int> Points2 = PointsWithinEnvelope(Shape2, Shape1.Extents); for (int I = 0; I < Points1.Count; I++) { for (int J = 0; J < Points2.Count; J++) { Point p1 = new Point(Shape1.get_Point(I)); Point p2 = new Point(Shape2.get_Point(J)); if (p1.Intersects(p2)) { return(true); } } } return(false); } // For lines and polygons simply test line segments in the area of interrest to see if they touch // (touching in this case just equates to having a minimum distance of 0. if ((Typ1 == ShapeCategories.Line || Typ1 == ShapeCategories.Polygon) && (Typ2 == ShapeCategories.Line || Typ2 == ShapeCategories.Polygon)) { List <LineSegment> Segs1 = LineSegmentsWithinEnvelope(Shape1, Shape2.Extents); List <LineSegment> Segs2 = LineSegmentsWithinEnvelope(Shape2, Shape1.Extents); for (int I = 0; I < Segs1.Count; I++) { for (int J = 0; J < Segs2.Count; J++) { if (Segs1[I].Intersects(Segs2[J])) { return(true); } } } return(false); } // multi-point to polygon if (Typ1 == ShapeCategories.MultiPoint) { List <int> Points1 = PointsWithinEnvelope(Shape1, Shape2.Extents); List <LineSegment> Segs2 = LineSegmentsWithinEnvelope(Shape2, Shape1.Extents); for (int I = 0; I < Points1.Count; I++) { for (int J = 0; J < Segs2.Count; J++) { if (Segs2[J].Intersects(Shape1.get_Point(Points1[I]))) { return(true); } } } return(false); } if (Typ2 == ShapeCategories.MultiPoint) { List <int> Points2 = PointsWithinEnvelope(Shape2, Shape1.Extents); List <LineSegment> Segs1 = LineSegmentsWithinEnvelope(Shape1, Shape2.Extents); for (int I = 0; I < Points2.Count; I++) { for (int J = 0; J < Segs1.Count; J++) { if (Segs1[J].Intersects(Shape2.get_Point(Points2[I]))) { return(true); } } } return(false); } return(false); }
// Returns only the point index values of the shapes in the interesection of the shape extents private static void LineSegmentsOfInterest(MapWinGIS.Shape Shape1, MapWinGIS.Shape Shape2, ref List <LineSegment> LineSegments1, ref List <LineSegment> LineSegments2) { Envelope Rect1, Rect2, rectIntersect; Rect1 = new Envelope(Shape1.Extents); Rect2 = new Envelope(Shape2.Extents); rectIntersect = (Envelope)Rect1.Intersection(Rect2); MapWinGIS.Point pt = new MapWinGIS.Point(); // reduce our points to points of interrest int numPoints1 = Shape1.numPoints; bool PreviousPointIncluded = true; // we will get the first point by wrapping from the last point for (int I = 0; I < numPoints1; I++) { pt = Shape1.get_Point(I); if (rectIntersect.Intersects(pt)) { if (PreviousPointIncluded == false) { // Add a segment back to the point LineSegments1.Add(new LineSegment(Shape1.get_Point(I - 1), pt)); } if (I == numPoints1 - 1) { LineSegments1.Add(new LineSegment(pt, Shape1.get_Point(0))); } else { LineSegments1.Add(new LineSegment(pt, Shape1.get_Point(I + 1))); } PreviousPointIncluded = true; } else { PreviousPointIncluded = false; } } int numPoints2 = Shape2.numPoints; PreviousPointIncluded = true; for (int I = 0; I < numPoints2; I++) { pt = Shape2.get_Point(I); if (rectIntersect.Intersects(pt)) { if (PreviousPointIncluded == false) { // Add a segment back to the point LineSegments2.Add(new LineSegment(Shape2.get_Point(I - 1), pt)); } if (I == numPoints2 - 1) { LineSegments2.Add(new LineSegment(pt, Shape2.get_Point(0))); } else { LineSegments2.Add(new LineSegment(pt, Shape2.get_Point(I + 1))); } PreviousPointIncluded = true; } else { PreviousPointIncluded = false; } } }
//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); }
/// <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); }
/// <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."); }
/// <summary> /// Finds the point that represents the "center of mass" for a polygon shape. /// </summary> /// <param name="polygon">The polygon shape.</param> /// <returns>The centroid: a point representing the center of mass of the polygon.</returns> public static MapWinGIS.Point Centroid(ref MapWinGIS.Shape polygon) { MapWinGIS.Point centroid = new MapWinGIS.PointClass(); // Centroid function only works for polygons - return something useful instead of causing // crashes in client apps if (!(polygon.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGON || polygon.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONZ || polygon.ShapeType == MapWinGIS.ShpfileType.SHP_POLYGONM)) { centroid.x = (polygon.Extents.xMax + polygon.Extents.xMin) / 2.0F; centroid.y = (polygon.Extents.yMax + polygon.Extents.yMin) / 2.0F; return(centroid); } Error.ClearErrorLog(); double area = Area(ref polygon); int numPoints = polygon.numPoints; int numParts = polygon.NumParts; double xSum = 0; double ySum = 0; if (numParts > 1) { //TO DO: determine how to handle this case //use the outermost part for finding the center???? //what about island chains? mulitple centroids exist. gErrorMsg = "Sorry, centroid cannot be computed for a multi-part polygon."; Error.SetErrorMsg(gErrorMsg); Debug.WriteLine(gErrorMsg); return(centroid); } else { for (int i = 0; i <= numPoints - 2; i++) { MapWinGIS.Point currPt = new MapWinGIS.PointClass(); currPt = polygon.get_Point(i); MapWinGIS.Point nextPt = new MapWinGIS.PointClass(); nextPt = polygon.get_Point(i + 1); double cProduct = (currPt.x * nextPt.y) - (nextPt.x * currPt.y); xSum += (currPt.x + nextPt.x) * cProduct; ySum += (currPt.y + nextPt.y) * cProduct; } } centroid.x = xSum / (6 * area); centroid.y = ySum / (6 * area); if (centroid.x < 0 && centroid.y < 0) { if (polygon.get_Point(0).x > 0) { //translation incorrect, flip centroid.x = -1 * centroid.x; } if (polygon.get_Point(0).y > 0) { centroid.y = -1 * centroid.y; } } return(centroid); }