From: John M. <geo...@ti...> - 2011-03-27 05:08:11
|
At 02:22 PM 3/27/2011 +1100, Michael Bedward wrote: Thanks The problem I have been having is apparently related to how I set the schema. I am using one from the existing file, and modifying it (the first element) from MultiPolygon to LineString. When I dump everything out, it looks fine, but when I try to write it to a shapefile... boom, an exception is thrown. It is driving me nuts. Unfortunately, it appears I need to understand all the details of what a type really means to build one. Sigh. I am taking the suggestion to post my code. It is quite a bit, as I don't know which things I am doing are necessary and which are redundant. However, you may be able to quickly see whatever I'm doing that's wrong. I am not even trying, at this point, to maintain the attributes of each line segment, because they are not important for the final solution. Anyway, the whole mess is at http://snippets.dzone.com/posts/show/13059 If you have the JTS libraries and geotools 2.7-M2, that single source file will compile and run. (I am using the recommended Maven approach). However, if you un-comment the line that writes the shapefile, it will blow up. I don't know why, and I would love to know. It may be that the code below will create a type that works. I haven't had a chance to try it yet. I hope that posting the code will show where I am going astray, so I don't have to keep asking dumb questions. ============ also ======== BTW, I tried cvs2shp example, but it fails on the following (once again, a problem with the feature type). I assume the example is out of sync with the version of the libraries I am using. */ final SimpleFeatureType TYPE = DataUtilities.createType( "Location", // <- the name for our feature type "location:Point:srid=4326," + // <- the geometry attribute: Point type "name:String" // <- a String attribute ); "location:Point:srid=4326" is the problem - it tries to look up 4326 and fails. I don't know what should go in there. The exception is: Exception in thread "main" org.geotools.feature.SchemaException: Error decoding srs: 4326 at org.geotools.data.DataUtilities.createAttribute(DataUtilities.java:2175) at org.geotools.data.DataUtilities.createType(DataUtilities.java:1752) at org.geotools.data.DataUtilities.createType(DataUtilities.java:1702) at map.examples.WriteShapeFileExample.main(WriteShapeFileExample.java:52) Thanks John >Hi John > > > The question is due to my weak understanding of the API: Given a collection > > of LineString geometries (say, Array or LinkedList) of line strings, > how can > > I turn that back into a shapefile? > >it's quite straightforward but first you need to decide what >attributes you want to associate with each LineString. Your input data >are state and county polygons, so perhaps you would want to record the >identifying code / abbreviation / whatever of each state and county >that each line string was associated with ? And for LineString that >was originally part of a country polygon boundary but not a state >boundary, would you want to have some sort of N/A code for the state >attribute, or record the state that it falls in ? > >Once you know all that (and after overcoming the simplification >challenges :) can create a feature type and line shapefile something >like this (edit for whatever attributes you are working with): > > private void makeShapefile(List<LineString> lines, >CoordinateReferenceSystem crs) { > SimpleFeatureTypeBuilder typeBuilder = new > SimpleFeatureTypeBuilder(); > typeBuilder.setName("Political"); > typeBuilder.setCRS(crs); // if you are using one > > typeBuilder.add("the_geom", LineString.class); > typeBuilder.add("id", Integer.class); > typeBuilder.add("state1", String.class); > typeBuilder.add("state2", String.class); > typeBuilder.add("county1", String.class); > typeBuilder.add("county2", String.class); > > final SimpleFeatureType TYPE = typeBuilder.buildFeatureType(); > > SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE); > > SimpleFeatureCollection fc = FeatureCollections.newCollection(); > > for (LineString line : lines) { > > int numVertices = line.getNumPoints(); > > LineSegment seg = new LineSegment( > line.getCoordinateN(0), > line.getCoordinateN(numVertices - 1)); > > LineData data = lineLookup.get(seg); > > featureBuilder.addAll(new Object[] { > line, > data.id, > data.state1, > data.state2, > data.county1, > data.county2 > }); > > fc.add(featureBuilder.buildFeature(String.valueOf(data.id))); > } > } > >Obviously I just made up those attributes to convey the general idea. >The code assumes that you have a small class to store the attribute >data for each line; something like this... > > class LineData { > int id; > String state1; > String state2; > String county1; > String county2; > } > >And also a Map like this to associate the data object with each LineString. > > Map<LineSegment, LineData> lineLookup; > >It is using the LineString end-points, expressed as a LineSegment >object, as the key. I suggest you use a Map rather than the >Geometry.setUserData method to store the data in your LineStrings >directly. The reason is that if you put your lines through one of the >JTS XXXSimplifiers at any stage they strip the user data from the >Geometries. > >Once you've got a SimpleFeatureCollection you can create a new >shapefile from it as in the cvs2shp example: > >http://docs.geotools.org/stable/userguide/examples/csv2shp.html > >Michael |