/// <summary> /// Adds an Edge, DirectedEdges, and Nodes for the given LineString representation /// of an edge. /// </summary> public virtual void AddEdge(LineString lineString) { if (lineString.IsEmpty) return; IList<Coordinate> coordinates = CoordinateArrays.RemoveRepeatedPoints(lineString.Coordinates); Coordinate startCoordinate = coordinates[0]; Coordinate endCoordinate = coordinates[coordinates.Count - 1]; Node startNode = GetNode(startCoordinate); Node endNode = GetNode(endCoordinate); DirectedEdge directedEdge0 = new LineMergeDirectedEdge(startNode, endNode, coordinates[1], true); DirectedEdge directedEdge1 = new LineMergeDirectedEdge(endNode, startNode, coordinates[coordinates.Count - 2], false); Edge edge = new LineMergeEdge(lineString); edge.SetDirectedEdges(directedEdge0, directedEdge1); Add(edge); }
/// <summary> /// The Voronoi Graph calculation creates a delaunay tesselation where /// each point is effectively converted into triangles. /// </summary> /// <param name="points">The points to use for creating the tesselation</param> /// <returns></returns> public static IFeatureSet DelaunayLines(IFeatureSet points) { double[] vertices = points.Vertex; VoronoiGraph gp = Fortune.ComputeVoronoiGraph(vertices); FeatureSet result = new FeatureSet(); foreach (VoronoiEdge edge in gp.Edges) { Coordinate c1 = edge.RightData.ToCoordinate(); Coordinate c2 = edge.LeftData.ToCoordinate(); LineString ls = new LineString(new List<Coordinate>{c1, c2}); Feature f = new Feature(ls); result.AddFeature(f); } return result; }
/// <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.LineString || shapeType == ShapeGeometryTypes.LineStringM || shapeType == ShapeGeometryTypes.LineStringZ || shapeType == ShapeGeometryTypes.LineStringZM )) throw new ShapefileException("Attempting to load a non-arc as arc."); //read and for now ignore bounds. double[] box = new double[4]; for (int i = 0; i < 4; i++) { double d= file.ReadDouble(); box[i] =d; } int numParts = file.ReadInt32(); int numPoints = file.ReadInt32(); int[] partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) partOffsets[i] = file.ReadInt32(); ILineString[] lines = new LineString[numParts]; 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(); Coordinate external; for (int i = 0; i < length; i++) { external = new Coordinate(file.ReadDouble(),file.ReadDouble()); // points.Add(geometryFactory.PrecisionModel.ToInternal(external)); new PrecisionModel(geometryFactory.PrecisionModel).MakePrecise(external); points.Add(external); } lines[part] = geometryFactory.CreateLineString(points.ToArray()); } return geometryFactory.CreateMultiLineString(lines); }
/// <summary> /// The Voronoi Graph calculation creates the lines that form a voronoi diagram /// </summary> /// <param name="points">The points to use for creating the tesselation</param> /// <returns></returns> public static IFeatureSet VoronoiLines(IFeatureSet points) { double[] vertices = points.Vertex; VoronoiGraph gp = Fortune.ComputeVoronoiGraph(vertices); HandleBoundaries(gp, points.Envelope); FeatureSet result = new FeatureSet(); foreach (VoronoiEdge edge in gp.Edges) { Coordinate c1 = edge.VVertexA.ToCoordinate(); Coordinate c2 = edge.VVertexB.ToCoordinate(); LineString ls = new LineString(new List<Coordinate> { c1, c2 }); Feature f = new Feature(ls); result.AddFeature(f); } return result; }
/// <summary> /// /// </summary> /// <param name="lineString"></param> /// <param name="writer"></param> protected virtual void Write(LineString lineString, XmlTextWriter writer) { writer.WriteStartElement("LineString"); Write(lineString.Coordinates, writer); writer.WriteEndElement(); }
/// <summary> /// /// </summary> /// <param name="lineString"></param> private void Add(LineString lineString) { if (factory == null) this.factory = lineString.Factory; graph.AddEdge(lineString); }
/// <summary> /// Allows for new behavior during deactivation. /// </summary> protected override void OnDeactivate() { if (_standBy) return; // Don't completely deactivate, but rather go into standby mode // where we draw only the content that we have actually locked in. _standBy = true; // base.OnDeactivate(); if(_coordinateDialog != null)_coordinateDialog.Hide(); if (_coordinates != null && _coordinates.Count > 1) { LineString ls = new LineString(_coordinates); FeatureSet fs = new FeatureSet(FeatureTypes.Line); fs.Features.Add(new Feature(ls)); MapLineLayer gll = new MapLineLayer(fs); //gll.Symbolizer.FillColor = Color.Blue; gll.Symbolizer.ScaleMode = ScaleModes.Symbolic; gll.Symbolizer.Smoothing = true; gll.MapFrame = Map.MapFrame; _tempLayer = gll; Map.MapFrame.DrawingLayers.Add(gll); // Map.MapFrame.Initialize(_tempLayer); Map.MapFrame.Invalidate(); Map.Invalidate(); } }
/// <summary> /// /// </summary> /// <param name="parentLine"></param> /// <param name="minimumSize"></param> public TaggedLineString(LineString parentLine, int minimumSize) { _parentLine = parentLine; _minimumSize = minimumSize; Init(); }
/// <summary> /// Add a <c>LineString</c> forming an edge of the polygon graph. /// </summary> /// <param name="line">The line to add.</param> public virtual void AddEdge(LineString line) { if (line.IsEmpty) return; IList<Coordinate> linePts = CoordinateArrays.RemoveRepeatedPoints(line.Coordinates); Coordinate startPt = linePts[0]; Coordinate endPt = linePts[linePts.Count - 1]; Node nStart = GetNode(startPt); Node nEnd = GetNode(endPt); DirectedEdge de0 = new PolygonizeDirectedEdge(nStart, nEnd, linePts[1], true); DirectedEdge de1 = new PolygonizeDirectedEdge(nEnd, nStart, linePts[linePts.Count - 2], false); Edge edge = new PolygonizeEdge(line); edge.SetDirectedEdges(de0, de1); Add(edge); }
/// <summary> /// Creates a <see cref="MultiLineString" /> in the reverse order to this object. /// Both the order of the component LineStrings /// and the order of their coordinate sequences are reversed. /// </summary> /// <returns>a <see cref="MultiLineString" /> in the reverse order.</returns> public virtual IMultiLineString Reverse() { int nLines = Geometries.Length; ILineString[] revLines = new LineString[nLines]; for (int i = 0; i < Geometries.Length; i++) revLines[nLines - 1 - i] = new LineString(((ILineString)Geometries[i]).Reverse()); return Factory.CreateMultiLineString(revLines); }
/// <summary> /// Constructs a LineMergeEdge with vertices given by the specified LineString. /// </summary> /// <param name="line"></param> public LineMergeEdge(LineString line) { this.line = line; }
/// <summary> /// If the input geometry is a singular basic geometry, this will become a collection of 1 geometry. /// If the input geometry is a multi- basic geometry, this will simply ensure that each member /// is upgraded to a full geometry. /// </summary> /// <param name="inGeometry"></param> /// <param name="inFactory"></param> public GeometryCollection(IBasicGeometry inGeometry, IGeometryFactory inFactory) : base(inFactory) { if (inGeometry == null) { _geometries = new IGeometry[] { }; return; } IBasicPolygon pg = inGeometry.GetBasicGeometryN(0) as IBasicPolygon; if (pg != null) { _geometries = new IGeometry[inGeometry.NumGeometries]; for (int iGeom = 0; iGeom < inGeometry.NumGeometries; iGeom++) { pg = inGeometry.GetBasicGeometryN(iGeom) as IBasicPolygon; _geometries[iGeom] = new Polygon(pg); } return; } IBasicPoint pt = inGeometry.GetBasicGeometryN(0) as IBasicPoint; if (pt != null) { _geometries = new IGeometry[inGeometry.NumGeometries]; for (int iGeom = 0; iGeom < inGeometry.NumGeometries; iGeom++) { pt = inGeometry.GetBasicGeometryN(iGeom) as IBasicPoint; _geometries[iGeom] = new Point(pt); } return; } IBasicLineString ls = inGeometry.GetBasicGeometryN(0) as IBasicLineString; if (ls != null) { _geometries = new IGeometry[inGeometry.NumGeometries]; for (int iGeom = 0; iGeom < inGeometry.NumGeometries; iGeom++) { ls = inGeometry.GetBasicGeometryN(iGeom) as IBasicLineString; _geometries[iGeom] = new LineString(ls); } return; } }
/// <summary> /// Creates a <c>MultiLineString</c> using the given <c>LineStrings</c>; a null or empty /// array will create an empty MultiLineString. /// </summary> /// <param name="lineStrings">LineStrings, each of which may be empty but not null-</param> public virtual IMultiLineString CreateMultiLineString(IBasicLineString[] lineStrings) { if (lineStrings == null) { return new MultiLineString(); } int count = lineStrings.Length; LineString[] ls = new LineString[count]; for (int I = 0; I < count; I++) { ls[I] = new LineString(lineStrings[I]); } MultiLineString temp = new MultiLineString(ls); return temp; }
/// <summary> /// /// </summary> /// <param name="geom"></param> /// <returns></returns> public virtual bool IsSimple(LineString geom) { return IsSimpleLinearGeometry(geom); }
/// <summary> /// Add a linestring to the graph of polygon edges. /// </summary> /// <param name="line">The <c>LineString</c> to add.</param> private void Add(LineString line) { // create a new graph using the factory from the input Geometry if (_graph == null) _graph = new PolygonizeGraph(line.Factory); _graph.AddEdge(line); }
/// <summary> /// /// </summary> /// <param name="lineString"></param> /// <returns></returns> protected virtual int SetByteStreamLength(LineString lineString) { int count = InitValue; count += lineString.NumPoints * CoordSize; return count; }
private static int CalcSiDeterm(ref IFeatureSet lineSF, ref IFeature polygon, ref int[] intersectsPerLineSeg, ref Point[][] intersectionPts, ref int[][] polyIntersectLocs) { int numSignChanges = 0; //tracks number of determinant sign changes int numLines = lineSF.Features.Count; int numVerticies = polygon.NumPoints; int[][] detSigns = new int[numLines][]; bool[][] signChanges = new bool[numLines][]; //keeps track of where sign changes occur int[][] changeLocations = new int[numLines][]; int[] intersectsPerLine = new int[numLines]; Point[][] intersectPts = new Point[numLines][]; IList<Coordinate> coorPoly = polygon.Coordinates; //ICoordinate[] secCoor = new ICoordinate[2]; for (int lineNo = 0; lineNo <= numLines - 1; lineNo++) { IFeature line = lineSF.Features[lineNo]; IList<Coordinate> secCoor; IList<Coordinate> coorLine = line.Coordinates; int numChangesPerLine = 0; detSigns[lineNo] = new int[numVerticies]; signChanges[lineNo] = new bool[numVerticies]; intersectPts[lineNo] = new Point[numVerticies]; changeLocations[lineNo] = new int[numVerticies]; for (int vertNo = 0; vertNo <= numVerticies - 1; vertNo++) { intersectPts[lineNo][vertNo] = new Point(); Point intersectPt = new Point(); // Calculate the determinant (3x3 square matrix) double si = TurboDeterm(coorPoly[vertNo].X, coorLine[0].X, coorLine[1].X, coorPoly[vertNo].Y, coorLine[0].Y, coorLine[1].Y); // Check the determinant result switch (vertNo) { case 0: if (si == 0) detSigns[lineNo][vertNo] = 0; // we have hit a vertex else if (si > 0) detSigns[lineNo][vertNo] = 1; // +'ve else if (si < 0) detSigns[lineNo][vertNo] = -1; // -'ve signChanges[lineNo][0] = false; // First element will NEVER be a sign change break; default: if (si == 0) detSigns[lineNo][vertNo] = 0; else if (si > 0) detSigns[lineNo][vertNo] = 1; else if (si < 0) detSigns[lineNo][vertNo] = -1; // Check for sign change if (detSigns[lineNo][vertNo - 1] != detSigns[lineNo][vertNo]) { secCoor = new List<Coordinate>(); secCoor.Add(coorPoly[vertNo - 1]); secCoor.Add(coorPoly[vertNo]); //calculate the actual intercept point LineString polyTestLine1 = new LineString(secCoor); secCoor = new List<Coordinate>(); secCoor.Add(coorLine[0]); secCoor.Add(coorLine[1]); LineString polyTestLine2 = new LineString(secCoor); bool validIntersect = polyTestLine1.Intersects(polyTestLine2); IGeometry inPt = polyTestLine1.Intersection(polyTestLine2); if (inPt.Coordinates.Count == 1) intersectPt = new Point(inPt.Coordinate); if (validIntersect) { signChanges[lineNo][vertNo] = true; numSignChanges += 1; numChangesPerLine += 1; intersectsPerLine[lineNo] = numChangesPerLine; //we want to store the valid intersect pts at the //beginning of the array so we don't have to search for them intersectPts[lineNo][numChangesPerLine - 1] = intersectPt; //keep track of where the intersect occurs in reference to polygon changeLocations[lineNo][numChangesPerLine - 1] = vertNo; //intersect pt occurs between vertNo-1 and vertNo } else { signChanges[lineNo][vertNo] = false; } } else { signChanges[lineNo][vertNo] = false; } break; }//end of switch } } polyIntersectLocs = changeLocations; intersectionPts = intersectPts; intersectsPerLineSeg = intersectsPerLine; return numSignChanges; }
/// <summary> /// Executes the DP line simplefy tool programaticaly /// Ping Yang Added it for external Testing /// </summary> /// <param name="input">The input polygon feature set</param> /// <param name="tolerance">The tolerance to use when simplefiying</param> /// <param name="output">The output polygon feature set</param> /// <returns></returns> public bool Execute(IFeatureSet input, double tolerance, IFeatureSet output) { //Validates the input and output data if (input == null || output == null) return false; //We copy all the fields foreach (DataColumn inputColumn in input.DataTable.Columns) output.DataTable.Columns.Add(new DataColumn(inputColumn.ColumnName, inputColumn.DataType)); int numTotalOldPoints = 0; int numTotalNewPoints = 0; for (int j = 0; j < input.Features.Count; j++) { int numOldPoints = 0; int numNewPoints = 0; Geometry geom = input.Features[j].BasicGeometry as Geometry; if (geom != null) numOldPoints = geom.NumPoints; numTotalOldPoints += numOldPoints; if (geom != null) { for (int part = 0; part < geom.NumGeometries; part++) { Geometry geomPart = (Geometry)geom.GetGeometryN(part); //do the simplification IList<Coordinate> oldCoords = geomPart.Coordinates; IList<Coordinate> newCoords = MapWindow.Analysis.Topology.Simplify.DouglasPeuckerLineSimplifier.Simplify(oldCoords, tolerance); //convert the coordinates back to a geometry Geometry newGeom = new LineString(newCoords); numNewPoints += newGeom.NumPoints; numTotalNewPoints += numNewPoints; Feature newFeature = new Feature(newGeom, output); foreach (DataColumn colSource in input.DataTable.Columns) newFeature.DataRow[colSource.ColumnName] = input.Features[j].DataRow[colSource.ColumnName]; } } } output.Save(); return true; }
/// <summary> /// This uses extent checking (rather than full polygon intersection checking). It will add /// any members that are either contained by or intersect with the specified region /// depending on the SelectionMode property. The order of operation is the region /// acting on the feature, so Contains, for instance, would work with points. /// </summary> /// <param name="region"></param> /// <param name="affectedArea">The affected area of this addition</param> /// <returns>True if any item was actually added to the collection</returns> public bool AddRegion(IEnvelope region, out IEnvelope affectedArea) { bool added = false; SuspendChanges(); affectedArea = new Envelope(); Stopwatch sw = new Stopwatch(); Stopwatch total = new Stopwatch(); total.Start(); foreach (IFeature f in FeatureList) { bool doAdd = false; if (_selectionMode == SelectionModes.IntersectsExtent) { if (region.Intersects(f.Envelope)) { Add(f); affectedArea.ExpandToInclude(f.Envelope); added = true; } } else if (_selectionMode == SelectionModes.ContainsExtent) { if (region.Contains(f.Envelope)) { Add(f); affectedArea.ExpandToInclude(f.Envelope); added = true; } } IGeometry reg; if(region.Width == 0 && region.Height == 0) { reg = new Point(region.X, region.Y); } else if (region.Height == 0 || region.Width == 0) { Coordinate[] coords = new Coordinate[2]; coords[0] = new Coordinate(region.X, region.Y); coords[1] = new Coordinate(region.Bottom(), region.Right()); reg = new LineString(coords); } else { reg = region.ToPolygon(); } IGeometry geom = Geometry.FromBasicGeometry(f.BasicGeometry); switch (_selectionMode) { case SelectionModes.Contains: if(region.Contains(f.Envelope)) { doAdd = true; } else if (region.Intersects(f.Envelope)) { if (reg.Contains(geom)) doAdd = true; } break; case SelectionModes.CoveredBy: if (reg.CoveredBy(geom)) doAdd = true; break; case SelectionModes.Covers: if (reg.Covers(geom)) doAdd = true; break; case SelectionModes.Disjoint: if (reg.Disjoint(geom)) doAdd = true; break; case SelectionModes.Intersects: if (region.Contains(f.Envelope)) { doAdd = true; } else if (region.Intersects(f.Envelope)) { if (reg.Intersects(geom)) doAdd = true; } break; case SelectionModes.Overlaps: if (reg.Overlaps(geom)) doAdd = true; break; case SelectionModes.Touches: if (reg.Touches(geom)) doAdd = true; break; case SelectionModes.Within: if (reg.Within(geom)) doAdd = true; break; } if (doAdd) { Add(f); affectedArea.ExpandToInclude(f.Envelope); added = true; } } sw.Start(); ResumeChanges(); sw.Stop(); total.Stop(); Debug.WriteLine("Geometry Intersection Time: " + sw.ElapsedMilliseconds); Debug.WriteLine("Total Intersection Time: " + total.ElapsedMilliseconds); return added; }
/// <summary> /// Executes the DP line simplefy tool programaticaly /// </summary> /// <param name="input">The input polygon feature set</param> /// <param name="tolerance">The tolerance to use when simplefiying</param> /// <param name="output">The output polygon feature set</param> /// <param name="cancelProgressHandler">The progress handler</param> /// <returns></returns> public bool Execute(IFeatureSet input, double tolerance, IFeatureSet output, ICancelProgressHandler cancelProgressHandler) { //Validates the input and output data if (input == null || output == null) return false; //We copy all the fields foreach (DataColumn inputColumn in input.DataTable.Columns) output.DataTable.Columns.Add(new DataColumn(inputColumn.ColumnName, inputColumn.DataType)); int numTotalOldPoints = 0; int numTotalNewPoints = 0; for (int j = 0; j < input.Features.Count; j++) { int numOldPoints = 0; int numNewPoints = 0; Geometry geom = input.Features[j].BasicGeometry as Geometry; if (geom != null) numOldPoints = geom.NumPoints; numTotalOldPoints += numOldPoints; if (geom != null) { for (int part = 0; part < geom.NumGeometries; part++) { Geometry geomPart = (Geometry)geom.GetGeometryN(part); //do the simplification IList<Coordinate> oldCoords = geomPart.Coordinates; IList<Coordinate> newCoords = MapWindow.Analysis.Topology.Simplify.DouglasPeuckerLineSimplifier.Simplify(oldCoords, tolerance); //convert the coordinates back to a geometry Geometry newGeom = new LineString(newCoords); numNewPoints += newGeom.NumPoints; numTotalNewPoints += numNewPoints; Feature newFeature = new Feature(newGeom, output); foreach (DataColumn colSource in input.DataTable.Columns) newFeature.DataRow[colSource.ColumnName] = input.Features[j].DataRow[colSource.ColumnName]; } } //Status updates is done here, shows number of old / new points cancelProgressHandler.Progress("", Convert.ToInt32((Convert.ToDouble(j) / Convert.ToDouble(input.Features.Count)) * 100), numOldPoints + "-->" + numNewPoints); if (cancelProgressHandler.Cancel) return false; } cancelProgressHandler.Progress("", 100, TextStrings.Originalnumberofpoints + numTotalOldPoints + " " + TextStrings.Newnumberofpoints + numTotalNewPoints); output.Save(); return true; }
/// <summary> /// /// </summary> /// <param name="reader"></param> /// <returns></returns> protected virtual IGeometry ReadMultiLineString(BinaryReader reader) { int numGeometries = reader.ReadInt32(); LineString[] strings = new LineString[numGeometries]; for (int i = 0; i < numGeometries; i++) { ReadByteOrder(reader); WkbGeometryTypes geometryType = (WkbGeometryTypes)reader.ReadInt32(); if (geometryType != WkbGeometryTypes.LineString) throw new ArgumentException("LineString feature expected"); strings[i] = ReadLineString(reader) as LineString ; } return Factory.CreateMultiLineString(strings); }
/// <summary> /// /// </summary> /// <param name="parentLine"></param> public TaggedLineString(LineString parentLine) : this(parentLine, 2) { }