/// <summary> /// Read a shapefile Point record. /// </summary> /// <param name="stream">Input stream.</param> /// <param name="record">Shapefile record to be updated.</param> private static void ReadPoint(Stream stream, ShapeFileRecord record) { // Points - add a single point. Point p = new System.Windows.Point(); p.X = ShapeFile.ReadDouble64_LE(stream); p.Y = ShapeFile.ReadDouble64_LE(stream); record.Points.Add(p); // Bounding Box. record.XMin = p.X; record.YMin = p.Y; record.XMax = record.XMin; record.YMax = record.YMin; }
/// <summary> /// Read a shapefile Polygon record. /// </summary> /// <param name="stream">Input stream.</param> /// <param name="record">Shapefile record to be updated.</param> private static void ReadPolygon(Stream stream, ShapeFileRecord record) { // Bounding Box. record.XMin = ShapeFile.ReadDouble64_LE(stream); record.YMin = ShapeFile.ReadDouble64_LE(stream); record.XMax = ShapeFile.ReadDouble64_LE(stream); record.YMax = ShapeFile.ReadDouble64_LE(stream); // Num Parts and Points. int numParts = ShapeFile.ReadInt32_LE(stream); int numPoints = ShapeFile.ReadInt32_LE(stream); // Parts. for (int i = 0; i < numParts; i++) { record.Parts.Add(ShapeFile.ReadInt32_LE(stream)); } // Points. for (int i = 0; i < numPoints; i++) { Point p = new Point(); p.X = ShapeFile.ReadDouble64_LE(stream); p.Y = ShapeFile.ReadDouble64_LE(stream); record.Points.Add(p); } }
/// <summary> /// Read a shapefile record. /// </summary> /// <param name="stream">Input stream.</param> public ShapeFileRecord ReadShapeFileRecord(Stream stream) { ShapeFileRecord record = new ShapeFileRecord(); // Record Header. record.RecordNumber = ShapeFile.ReadInt32_BE(stream); record.ContentLength = ShapeFile.ReadInt32_BE(stream); // Shape Type. record.ShapeType = ShapeFile.ReadInt32_LE(stream); // Read the shape geometry, depending on its type. switch (record.ShapeType) { case (int)ShapeType.NullShape: // Do nothing. break; case (int)ShapeType.Point: ShapeFile.ReadPoint(stream, record); break; case (int)ShapeType.PolyLine: // PolyLine has exact same structure as Polygon in shapefile. ShapeFile.ReadPolygon(stream, record); break; case (int)ShapeType.Polygon: ShapeFile.ReadPolygon(stream, record); break; case (int)ShapeType.Multipoint: ShapeFile.ReadMultipoint(stream, record); break; default: { string msg = String.Format(System.Globalization.CultureInfo.InvariantCulture, "ShapeType {0} is not supported.", (int)record.ShapeType); throw new FileFormatException(msg); } } // Add the record to our internal list. this.records.Add(record); return record; }
/// <summary> /// Create a WPF shape given a shapefile record. /// </summary> /// <param name="shapeName">The name of the WPF shape.</param> /// <param name="record">Shapefile record.</param> /// <returns>The created WPF shape.</returns> private Shape CreateWPFShape(string shapeName, ShapeFileRecord record) { // Create a new geometry. Geometry geometry; if ( this.geometryType == GeometryType.UsePathGeometry ) geometry = this.CreatePathGeometry(record); else geometry = this.CreateStreamGeometry(record); // Transform the geometry based on current zoom and pan settings. geometry.Transform = this.viewTransform; // Create a new WPF Path. System.Windows.Shapes.Path path = new System.Windows.Shapes.Path(); // Assign the geometry to the path and set its name. path.Data = geometry; path.Name = shapeName; // Set path properties. path.StrokeThickness = 0.5; if ( record.ShapeType == (int)ShapeType.Polygon ) { path.Stroke = this.strokeBrush; path.Fill = this.GetRandomShapeBrush(); } else { path.Stroke = Brushes.DimGray; } // Return the created WPF shape. return path; }
/// <summary> /// Create a WPF shape to represent a shapefile point or /// multipoint record. /// </summary> /// <param name="shapeName">The name of the WPF shape.</param> /// <param name="record">Shapefile record.</param> /// <returns>The created WPF shape.</returns> private Shape CreateWPFPoint(string shapeName, ShapeFileRecord record) { // Create a new geometry. GeometryGroup geometry = new GeometryGroup(); // Add ellipse geometries to the group. foreach (Point pt in record.Points) { // Create a new ellipse geometry. EllipseGeometry ellipseGeo = new EllipseGeometry(); // Transform center point of the ellipse from lon/lat to // canvas coordinates. ellipseGeo.Center = this.shapeTransform.Transform(pt); // Set the size of the ellipse. ellipseGeo.RadiusX = 0.1; ellipseGeo.RadiusY = 0.1; // Add the ellipse to the geometry group. geometry.Children.Add(ellipseGeo); } // Transform the geometry based on current zoom and pan settings. geometry.Transform = this.viewTransform; // Add the geometry to a new Path and set path properties. System.Windows.Shapes.Path path = new System.Windows.Shapes.Path(); path.Data = geometry; path.Name = shapeName; path.Fill = Brushes.Crimson; path.StrokeThickness = 1; path.Stroke = Brushes.DimGray; // Return the created WPF shape. return path; }
/// <summary> /// Create a StreamGeometry given a shapefile record. /// </summary> /// <param name="record">Shapefile record.</param> /// <returns>A StreamGeometry instance.</returns> private Geometry CreateStreamGeometry(ShapeFileRecord record) { // Create a new stream geometry. StreamGeometry geometry = new StreamGeometry(); // Obtain the stream geometry context for drawing each part. using (StreamGeometryContext ctx = geometry.Open()) { // Draw figures. for (int i = 0; i < record.NumberOfParts; i++) { // Determine the starting index and the end index // into the points array that defines the figure. int start = record.Parts[i]; int end; if (record.NumberOfParts > 1 && i != (record.NumberOfParts - 1)) end = record.Parts[i + 1]; else end = record.NumberOfPoints; // Draw the figure. for (int j = start; j < end; j++) { System.Windows.Point pt = record.Points[j]; // Transform from lon/lat to canvas coordinates. pt = this.shapeTransform.Transform(pt); // Decide if the line segments are stroked or not. For the // PolyLine type it must be stroked. bool isStroked = (record.ShapeType == (int)ShapeType.PolyLine) || !(this.geometryType == GeometryType.UseStreamGeometryNotStroked); // Register the drawing instruction. if (j == start) ctx.BeginFigure(pt, true, false); else ctx.LineTo(pt, isStroked, true); } } } // Return the created stream geometry. return geometry; }
/// <summary> /// Create a PathGeometry given a shapefile record. /// </summary> /// <param name="record">Shapefile record.</param> /// <returns>A PathGeometry instance.</returns> private Geometry CreatePathGeometry(ShapeFileRecord record) { // Create a new geometry. PathGeometry geometry = new PathGeometry(); // Add figures to the geometry. for (int i = 0; i < record.NumberOfParts; i++) { // Create a new path figure. PathFigure figure = new PathFigure(); // Determine the starting index and the end index // into the points array that defines the figure. int start = record.Parts[i]; int end; if (record.NumberOfParts > 1 && i != (record.NumberOfParts - 1)) end = record.Parts[i + 1]; else end = record.NumberOfPoints; // Add line segments to the figure. for (int j = start; j < end; j++) { System.Windows.Point pt = record.Points[j]; // Transform from lon/lat to canvas coordinates. pt = this.shapeTransform.Transform(pt); if (j == start) figure.StartPoint = pt; else figure.Segments.Add(new LineSegment(pt, true)); } // Add the new figure to the geometry. geometry.Figures.Add(figure); } // Return the created path geometry. return geometry; }