MultiLineHandler.java
/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
/*
* Copyright (c) 2003 Open Source Geospatial Foundation, All rights reserved.
*
* This program and the accompanying materials are made available under the terms
* of the OSGeo BSD License v1.0 available at:
*
* https://www.osgeo.org/sites/osgeo.org/files/Page/osgeo-bsd-license.txt
*/
package org.locationtech.jtstest.testbuilder.io.shapefile;
import java.io.IOException;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.MultiLineString;
import org.locationtech.jts.geom.PrecisionModel;
/**
* Wrapper for a Shapefile arc.
*/
public class MultiLineHandler implements ShapeHandler {
int myShapeType = -1;
private PrecisionModel precisionModel = new PrecisionModel();
private GeometryFactory geometryFactory = new GeometryFactory(precisionModel, 0);
public MultiLineHandler()
{
myShapeType = 3;
}
public MultiLineHandler(int type) throws InvalidShapefileException
{
if ( (type != 3) && (type != 13) && (type != 23) )
throw new InvalidShapefileException("MultiLineHandler constructor - expected type to be 3,13 or 23");
myShapeType = type;
}
public Geometry read( EndianDataInputStream file , GeometryFactory geometryFactory, int contentLength) throws IOException,InvalidShapefileException
{
double junk;
int actualReadWords = 0; //actual number of words read (word = 16bits)
//file.setLittleEndianMode(true);
int shapeType = file.readIntLE();
actualReadWords += 2;
if (shapeType ==0)
{
return geometryFactory.createMultiLineString(null); //null shape
}
if (shapeType != myShapeType)
{
throw new InvalidShapefileException("MultilineHandler.read() - file says its type "+shapeType+" but i'm expecting type "+myShapeType);
}
//read bounding box (not needed)
junk = file.readDoubleLE();
junk =file.readDoubleLE();
junk =file.readDoubleLE();
junk =file.readDoubleLE();
actualReadWords += 4*4;
int numParts = file.readIntLE();
int numPoints = file.readIntLE();//total number of points
actualReadWords += 4;
int[] partOffsets = new int[numParts];
//points = new Coordinate[numPoints];
for ( int i = 0; i < numParts; i++ ){
partOffsets[i]=file.readIntLE();
actualReadWords += 2;
}
LineString lines[] = new LineString[numParts];
Coordinate[] coords = new Coordinate[numPoints];
for (int t =0;t<numPoints; t++)
{
coords[t] = new Coordinate(file.readDoubleLE(),file.readDoubleLE());
actualReadWords += 8;
}
if (myShapeType ==13)
{
junk =file.readDoubleLE(); //z min, max
junk =file.readDoubleLE();
actualReadWords += 8;
for (int t =0;t<numPoints; t++)
{
coords[t].setZ(file.readDoubleLE()); //z value
actualReadWords += 4;
}
}
if (myShapeType >=13)
{
// int fullLength = 22 + 2*numParts + (numPoints * 8) + 4+4+4*numPoints+ 4+4+4*numPoints;
int fullLength;
if (myShapeType == 13)
{
//polylineZ (with M)
fullLength = 22 + 2*numParts + (numPoints * 8) + 4+4+4*numPoints+ 4+4+4*numPoints;
}
else
{
// polylineM (with M)
fullLength = 22 + 2*numParts + (numPoints * 8) + 4+4+4*numPoints;
}
if (contentLength >= fullLength) //are ms actually there?
{
junk =file.readDoubleLE(); //m min, max
junk =file.readDoubleLE();
actualReadWords += 8;
for (int t =0;t<numPoints; t++)
{
junk =file.readDoubleLE(); //m value
actualReadWords += 4;
}
}
}
//verify that we have read everything we need
while (actualReadWords < contentLength)
{
int junk2 = file.readShortBE();
actualReadWords += 1;
}
int offset = 0;
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;
Coordinate points[] = new Coordinate[length];
for(int i=0;i<length;i++){
points[i]=coords[offset];
offset++;
}
lines[part] = geometryFactory.createLineString(points);
}
if (numParts ==1)
return lines[0];
else
return geometryFactory.createMultiLineString(lines);
}
/**
* Get the type of shape stored (Shapefile.ARC)
*/
public int getShapeType(){
return myShapeType;
}
public int getLength(Geometry geometry){
MultiLineString multi = (MultiLineString) geometry;
int numlines, numpoints;
numlines = multi.getNumGeometries();
numpoints = multi.getNumPoints();
if (myShapeType == 3)
{
return 22 + 2*numlines + (numpoints * 8);
}
if (myShapeType == 23)
{
return 22 + 2*numlines + (numpoints * 8) + 4+4+4*numpoints;
}
return 22 + 2*numlines + (numpoints * 8) + 4+4+4*numpoints+ 4+4+4*numpoints;
// return 22 + 2*numlines + (numpoints * 8);
//return (44+(4*((GeometryCollection)geometry).getNumGeometries()));
}
double[] zMinMax(Geometry g)
{
double zmin,zmax;
boolean validZFound = false;
Coordinate[] cs = g.getCoordinates();
double[] result = new double[2];
zmin = Double.NaN;
zmax = Double.NaN;
double z;
for (int t=0;t<cs.length; t++)
{
z= cs[t].getZ() ;
if (!(Double.isNaN( z ) ))
{
if (validZFound)
{
if (z < zmin)
zmin = z;
if (z > zmax)
zmax = z;
}
else
{
validZFound = true;
zmin = z ;
zmax = z ;
}
}
}
result[0] = (zmin);
result[1] = (zmax);
return result;
}
}
/*
* $Log: MultiLineHandler.java,v $
* Revision 1.1 2009/10/14 04:21:21 mbdavis
* added drag-n-drop for reading shp files
*
* Revision 1.4 2003/07/25 18:49:15 dblasby
* Allow "extra" data after the content. Fixes the ICI shapefile bug.
*
* Revision 1.3 2003/02/04 02:10:37 jaquino
* Feature: EditWMSQuery dialog
*
* Revision 1.2 2003/01/22 18:31:05 jaquino
* Enh: Make About Box configurable
*
* Revision 1.3 2002/10/30 22:36:11 dblasby
* Line reader now returns LINESTRING(..) if there is only one part to the arc
* polyline.
*
* Revision 1.2 2002/09/09 20:46:22 dblasby
* Removed LEDatastream refs and replaced with EndianData[in/out]putstream
*
* Revision 1.1 2002/08/27 21:04:58 dblasby
* original
*
* Revision 1.2 2002/03/05 10:23:59 jmacgill
* made sure geometries were created using the factory methods
*
* Revision 1.1 2002/02/28 00:38:50 jmacgill
* Renamed files to more intuitve names
*
* Revision 1.3 2002/02/13 00:23:53 jmacgill
* First semi working JTS version of Shapefile code
*
* Revision 1.2 2002/02/11 18:42:45 jmacgill
* changed read and write statements so that they produce and take Geometry objects instead of specific MultiLine objects
* changed parts[] array name to partOffsets[] for clarity and consistency with ShapePolygon
*
* Revision 1.1 2002/02/11 16:54:43 jmacgill
* added shapefile code and directories
*
*/