All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lejos.robotics.mapping.ShapefileLoader Maven / Gradle / Ivy

Go to download

leJOS (pronounced like the Spanish word "lejos" for "far") is a tiny Java Virtual Machine. In 2013 it was ported to the LEGO EV3 brick.

The newest version!
package lejos.robotics.mapping;

import java.io.*;
import java.util.ArrayList;

import lejos.robotics.geometry.Line;
import lejos.robotics.geometry.Rectangle;


/**
 * 

This class loads map data from a Shapefile and produces a LineMap object, which can * be used by the leJOS navigation package.

* *

There are many map editors which can use the Shapefile format (OpenEV, Global Mapper). Once you * have created a map, export it as Shapefile. This will produce three files ending in .shp .shx and * .dbf. The only file used by this class is .shp.

* *

NOTE: Shapefiles can only contain one type of shape data (polygon or polyline, not both). A single file can't * mix polylines with polygons.

* *

This class' code can parse points and multipoints. However, a LineMap object can't deal with * points (only lines) so points and multipoints are discarded.

* * @author BB * */ public class ShapefileLoader { /* OTHER POTENTIAL MAP FILE FORMATS TO ADD: * (none have really been researched yet for viability) * KML * GML * WMS? (more of a service than a file) * MIF/MID (MapInfo) * SVG (Scalable Vector Graphics) * EPS (Encapsulated Post Script) * DXF (Autodesk) * AI (Adobe Illustrator) * */ // 2D shape types types: private static final byte NULL_SHAPE = 0; private static final byte POINT = 1; private static final byte POLYLINE = 3; private static final byte POLYGON = 5; private static final byte MULTIPOINT = 8; private final int SHAPEFILE_ID = 0x0000270a; DataInputStream data_is = null; /** * Creates a ShapefileLoader object using an input stream. Likely you will use a FileInputStream * which points to the *.shp file containing the map data. * @param in */ public ShapefileLoader(InputStream in) { this.data_is = new DataInputStream(in); } /** * Retrieves a LineMap object from the Shapefile input stream. * @return the line map * @throws IOException */ public LineMap readLineMap() throws IOException { ArrayList lines = new ArrayList (); int fileCode = data_is.readInt(); // Big Endian if(fileCode != SHAPEFILE_ID) throw new IOException("File is not a Shapefile"); data_is.skipBytes(20); // Five int32 unused by Shapefile /*int fileLength =*/ data_is.readInt(); //System.out.println("Length: " + fileLength); // TODO: Docs say length is in 16-bit words. Unsure if this is strictly correct. Seems higher than what hex editor shows. /*int version =*/ readLEInt(); //System.out.println("Version: " + version); /*int shapeType =*/ readLEInt(); //System.out.println("Shape type: " + shapeType); // These x and y min/max values define bounding rectangle: double xMin = readLEDouble(); double yMin = readLEDouble(); double xMax = readLEDouble(); double yMax = readLEDouble(); // Create bounding rectangle: Rectangle rect = new Rectangle((float)xMin, (float)yMin, (float)(xMax - xMin), (float)(yMax - yMin)); /*double zMin =*/ readLEDouble(); /*double zMax =*/ readLEDouble(); /*double mMin =*/ readLEDouble(); /*double mMax =*/ readLEDouble(); // TODO These values seem to be rounded down to nearest 0.5. Must round them up? //System.out.println("Xmin " + xMin + " Ymin " + yMin); //System.out.println("Xmax " + xMax + " Ymax " + yMax); try { // TODO: This is a cheesy way to detect EOF condition. Not very good coding. while(2 > 1) { // TODO: Temp code to keep it looping. Should really detect EOF condition. // NOW ONTO READING INDIVIDUAL SHAPES: // Record Header (2 values): /*int recordNum =*/ data_is.readInt(); int recordLen = data_is.readInt(); // TODO: in 16-bit words. Might cause bug if number of shapes gets bigger than 16-bit short? // Record (variable length depending on shape type): int recShapeType = readLEInt(); // Now to read the actual shape data switch (recShapeType) { case NULL_SHAPE: break; case POINT: // DO WE REALLY NEED TO DEAL WITH POINT? Feature might use them possibly. /*double pointX =*/ readLEDouble(); // TODO: skip bytes instead /*double pointY =*/ readLEDouble(); break; case POLYLINE: // NOTE: Data structure for polygon/polyline is identical. Code should work for both. case POLYGON: // Polygons can contain multiple polygons, such as a donut with outer ring and inner ring for hole. // Max bounding rect: 4 doubles in a row. TODO: Discard bounding rect. values and skip instead. /*double polyxMin =*/ readLEDouble(); /*double polyyMin =*/ readLEDouble(); /*double polyxMax =*/ readLEDouble(); /*double polyyMax =*/ readLEDouble(); int numParts = readLEInt(); int numPoints = readLEInt(); // Retrieve array of indexes for each part in the polygon int [] partIndex = new int[numParts]; for(int i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy