private void makeRadialWall( DrawContext dc, double[] radii, double angle, double[] altitudes, boolean[] terrainConformant, int pillars, int stacks, int orientation, Vec4 referenceCenter, Geometry dest) { GeometryBuilder gb = this.getGeometryBuilder(); gb.setOrientation(orientation); float height = (float) (altitudes[1] - altitudes[0]); int count = gb.getRadialWallVertexCount(pillars, stacks); int numCoords = 3 * count; float[] verts = new float[numCoords]; float[] norms = new float[numCoords]; gb.makeRadialWallVertices( (float) radii[0], (float) radii[1], height, (float) angle, pillars, stacks, verts); this.makeRadialWallTerrainConformant( dc, pillars, stacks, verts, altitudes, terrainConformant, referenceCenter); gb.makeRadialWallNormals( (float) radii[0], (float) radii[1], height, (float) angle, pillars, stacks, norms); dest.setVertexData(count, verts); dest.setNormalData(count, norms); }
private void makePartialCylinder( DrawContext dc, double radius, double[] altitudes, boolean[] terrainConformant, int slices, int stacks, int orientation, double start, double sweep, Vec4 referenceCenter, Geometry dest) { GeometryBuilder gb = this.getGeometryBuilder(); gb.setOrientation(orientation); float height = (float) (altitudes[1] - altitudes[0]); int count = gb.getPartialCylinderVertexCount(slices, stacks); int numCoords = 3 * count; float[] verts = new float[numCoords]; float[] norms = new float[numCoords]; gb.makePartialCylinderVertices( (float) radius, height, slices, stacks, (float) start, (float) sweep, verts); gb.makePartialCylinderNormals( (float) radius, height, slices, stacks, (float) start, (float) sweep, norms); this.makePartialCylinderTerrainConformant( dc, slices, stacks, verts, altitudes, terrainConformant, referenceCenter); dest.setVertexData(count, verts); dest.setNormalData(count, norms); }
private void makeSectionOutlineIndices( int subdivisions, int vertexPos, int indexPos, int[] indices, boolean beginEdgeFlag, boolean endEdgeFlag) { GeometryBuilder gb = this.getGeometryBuilder(); int count = gb.getSubdivisionPointsVertexCount(subdivisions); int index = indexPos; int pos, nextPos; if (beginEdgeFlag) { pos = vertexPos; indices[index++] = pos; indices[index++] = pos + 1; } for (int i = 0; i < count - 1; i++) { pos = vertexPos + 2 * i; nextPos = vertexPos + 2 * (i + 1); indices[index++] = pos; indices[index++] = nextPos; indices[index++] = pos + 1; indices[index++] = nextPos + 1; } if (endEdgeFlag) { pos = vertexPos + 2 * (count - 1); indices[index++] = pos; indices[index] = pos + 1; } }
protected void makeTessellatedLocations( Globe globe, int subdivisions, List<LatLon> locations, List<LatLon> tessellatedLocations) { ArrayList<Vec4> points = new ArrayList<Vec4>(); for (LatLon ll : locations) { points.add(globe.computePointFromLocation(ll)); } //noinspection StringEquality if (WWMath.computeWindingOrderOfLocations(locations) != AVKey.COUNTER_CLOCKWISE) Collections.reverse(locations); Vec4 centerPoint = Vec4.computeAveragePoint(points); Vec4 surfaceNormal = globe.computeSurfaceNormalAtPoint(centerPoint); int numPoints = points.size(); float[] coords = new float[3 * numPoints]; for (int i = 0; i < numPoints; i++) { points.get(i).toFloatArray(coords, 3 * i, 3); } GeometryBuilder gb = new GeometryBuilder(); GeometryBuilder.IndexedTriangleArray tessellatedPoints = gb.tessellatePolygon(0, numPoints, coords, surfaceNormal); for (int i = 0; i < subdivisions; i++) { gb.subdivideIndexedTriangleArray(tessellatedPoints); } for (int i = 0; i < tessellatedPoints.getVertexCount(); i++) { Vec4 v = Vec4.fromFloatArray(tessellatedPoints.getVertices(), 3 * i, 3); tessellatedLocations.add(globe.computePositionFromPoint(v)); } }
@Override protected List<Vec4> computeMinimalGeometry(Globe globe, double verticalExaggeration) { double[] angles = this.computeAngles(); // Angles are equal, fall back to building a closed cylinder. if (angles == null) return super.computeMinimalGeometry(globe, verticalExaggeration); double[] radii = this.getRadii(); Matrix transform = this.computeTransform(globe, verticalExaggeration); GeometryBuilder gb = this.getGeometryBuilder(); int count = gb.getPartialDiskVertexCount(MINIMAL_GEOMETRY_SLICES, MINIMAL_GEOMETRY_LOOPS); int numCoords = 3 * count; float[] verts = new float[numCoords]; gb.makePartialDiskVertices( (float) radii[0], (float) radii[1], // Inner radius, outer radius. MINIMAL_GEOMETRY_SLICES, MINIMAL_GEOMETRY_LOOPS, // Slices, loops, (float) angles[0], (float) angles[2], // Start angle, sweep angle. verts); List<LatLon> locations = new ArrayList<LatLon>(); for (int i = 0; i < numCoords; i += 3) { Vec4 v = new Vec4(verts[i], verts[i + 1], verts[i + 2]); v = v.transformBy4(transform); locations.add(globe.computePositionFromPoint(v)); } ArrayList<Vec4> points = new ArrayList<Vec4>(); this.makeExtremePoints(globe, verticalExaggeration, locations, points); return points; }
private int getSectionOutlineIndexCount( int subdivisions, boolean beginEdgeFlag, boolean endEdgeFlag) { GeometryBuilder gb = this.getGeometryBuilder(); int count = 4 * (gb.getSubdivisionPointsVertexCount(subdivisions) - 1); if (beginEdgeFlag) count += 2; if (endEdgeFlag) count += 2; return count; }
private void makeEdge( DrawContext dc, int count, float[] locations, Boolean[] edgeFlags, double[] altitudes, boolean[] terrainConformant, int subdivisions, int orientation, Matrix locationTransform, Vec4 referenceCenter, int fillIndexPos, int[] fillIndices, int outlineIndexPos, int[] outlineIndices, int vertexPos, float[] vertices, float[] normals) { GeometryBuilder gb = this.getGeometryBuilder(); gb.setOrientation(orientation); int sectionFillIndexCount = this.getSectionFillIndexCount(subdivisions); int sectionVertexCount = this.getSectionVertexCount(subdivisions); for (int i = 0; i < count - 1; i++) { boolean beginEdgeFlag = edgeFlags[i]; boolean endEdgeFlag = edgeFlags[i + 1]; this.makeSectionFillIndices(subdivisions, vertexPos, fillIndexPos, fillIndices); this.makeSectionOutlineIndices( subdivisions, vertexPos, outlineIndexPos, outlineIndices, beginEdgeFlag, endEdgeFlag); this.makeSectionVertices( dc, i, locations, altitudes, terrainConformant, subdivisions, locationTransform, referenceCenter, vertexPos, vertices); gb.makeIndexedTriangleArrayNormals( fillIndexPos, sectionFillIndexCount, fillIndices, vertexPos, sectionVertexCount, vertices, normals); fillIndexPos += sectionFillIndexCount; outlineIndexPos += this.getSectionOutlineIndexCount(subdivisions, beginEdgeFlag, endEdgeFlag); vertexPos += sectionVertexCount; } }
private void makePartialDiskIndices(int slices, int loops, int orientation, Geometry dest) { GeometryBuilder gb = this.getGeometryBuilder(); gb.setOrientation(orientation); int mode = gb.getPartialDiskDrawMode(); int count = gb.getPartialDiskIndexCount(slices, loops); int[] indices = new int[count]; gb.makePartialDiskIndices(slices, loops, indices); dest.setElementData(mode, count, indices); }
private void makeRadialWallIndices(int pillars, int stacks, int orientation, Geometry dest) { GeometryBuilder gb = this.getGeometryBuilder(); gb.setOrientation(orientation); int mode = gb.getRadialWallDrawMode(); int count = gb.getRadialWallIndexCount(pillars, stacks); int[] indices = new int[count]; gb.makeRadialWallIndices(pillars, stacks, indices); dest.setElementData(mode, count, indices); }
private void makeCap( DrawContext dc, GeometryBuilder.IndexedTriangleArray ita, double altitude, boolean terrainConformant, int orientation, Matrix locationTransform, Vec4 referenceCenter, int indexPos, int[] indices, int vertexPos, float[] vertices, float[] normals) { GeometryBuilder gb = this.getGeometryBuilder(); Globe globe = dc.getGlobe(); int indexCount = ita.getIndexCount(); int vertexCount = ita.getVertexCount(); int[] locationIndices = ita.getIndices(); float[] locationVerts = ita.getVertices(); this.copyIndexArray( indexCount, (orientation == GeometryBuilder.INSIDE), locationIndices, vertexPos, indexPos, indices); for (int i = 0; i < vertexCount; i++) { int index = 3 * i; Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]); vec = vec.transformBy4(locationTransform); Position pos = globe.computePositionFromPoint(vec); vec = this.computePointFromPosition( dc, pos.getLatitude(), pos.getLongitude(), altitude, terrainConformant); index = 3 * (vertexPos + i); vertices[index] = (float) (vec.x - referenceCenter.x); vertices[index + 1] = (float) (vec.y - referenceCenter.y); vertices[index + 2] = (float) (vec.z - referenceCenter.z); } gb.makeIndexedTriangleArrayNormals( indexPos, indexCount, indices, vertexPos, vertexCount, vertices, normals); }
private void makeSectionVertices( DrawContext dc, int locationPos, float[] locations, double[] altitude, boolean[] terrainConformant, int subdivisions, Matrix locationTransform, Vec4 referenceCenter, int vertexPos, float[] vertices) { GeometryBuilder gb = this.getGeometryBuilder(); int numPoints = gb.getSubdivisionPointsVertexCount(subdivisions); Globe globe = dc.getGlobe(); int index1 = 3 * locationPos; int index2 = 3 * (locationPos + 1); float[] locationVerts = new float[3 * numPoints]; gb.makeSubdivisionPoints( locations[index1], locations[index1 + 1], locations[index1 + 2], locations[index2], locations[index2 + 1], locations[index2 + 2], subdivisions, locationVerts); for (int i = 0; i < numPoints; i++) { int index = 3 * i; Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]); vec = vec.transformBy4(locationTransform); Position pos = globe.computePositionFromPoint(vec); for (int j = 0; j < 2; j++) { vec = this.computePointFromPosition( dc, pos.getLatitude(), pos.getLongitude(), altitude[j], terrainConformant[j]); index = 2 * i + j; index = 3 * (vertexPos + index); vertices[index] = (float) (vec.x - referenceCenter.x); vertices[index + 1] = (float) (vec.y - referenceCenter.y); vertices[index + 2] = (float) (vec.z - referenceCenter.z); } } }
private static boolean polygonToLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof Polygon && LineString.class == targetType) { Polygon polygon = (Polygon) geom; result.add( geomBuilder.safeCreateGeometry( LineString.class, polygon.getExteriorRing().getCoordinates())); int i = 0; while (i < polygon.getNumInteriorRing()) { result.add( geomBuilder.safeCreateGeometry( LineString.class, polygon.getInteriorRingN(i).getCoordinates())); i++; } return true; } return false; }
private void makeSectionFillIndices( int subdivisions, int vertexPos, int indexPos, int[] indices) { GeometryBuilder gb = this.getGeometryBuilder(); int count = gb.getSubdivisionPointsVertexCount(subdivisions); int index = indexPos; int pos, nextPos; for (int i = 0; i < count - 1; i++) { pos = vertexPos + 2 * i; nextPos = vertexPos + 2 * (i + 1); indices[index++] = pos + 1; indices[index++] = pos; indices[index++] = nextPos + 1; indices[index++] = nextPos + 1; indices[index++] = pos; indices[index++] = nextPos; } }
private static boolean simpleToMultiPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof GeometryCollection) && MultiPolygon.class == targetType) { result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates())); return true; } return false; }
private static boolean collectionToMultiPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && geom instanceof GeometryCollection && MultiPolygon.class == targetType) { for (int i = 0; i < geom.getNumGeometries(); i++) { result.add( geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates())); } return true; } return false; }
public void testPrimFactCRS() throws UnsupportedOperationException, FactoryException { CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84; GeometryBuilder builder = new GeometryBuilder(crs); CoordinateReferenceSystem crs2 = CRS.parseWKT(crs.toWKT()); GeometryBuilder builder2 = new GeometryBuilder(crs2); // create a list of connected positions List<Position> dps = new ArrayList<Position>(); dps.add(builder.createDirectPosition(new double[] {20, 10})); dps.add(builder.createDirectPosition(new double[] {40, 10})); dps.add(builder.createDirectPosition(new double[] {50, 40})); dps.add(builder.createDirectPosition(new double[] {30, 50})); dps.add(builder.createDirectPosition(new double[] {10, 30})); dps.add(builder.createDirectPosition(new double[] {20, 10})); // create linestring from directpositions LineString line = builder.createLineString(dps); // create curvesegments from line ArrayList<CurveSegment> segs = new ArrayList<CurveSegment>(); segs.add(line); // Create list of OrientableCurves that make up the surface OrientableCurve curve = builder.createCurve(segs); List<OrientableCurve> orientableCurves = new ArrayList<OrientableCurve>(); orientableCurves.add(curve); // create the interior ring and a list of empty interior rings (holes) Ring extRing = builder2.createRing(orientableCurves); List<Ring> intRings = new ArrayList<Ring>(); // create the surfaceboundary from the rings SurfaceBoundary sb = builder2.createSurfaceBoundary(extRing, intRings); // create the surface Surface surface = builder2.createSurface(sb); }
private void makePartialDisk( DrawContext dc, double[] radii, double altitude, boolean terrainConformant, int slices, int loops, int orientation, double start, double sweep, Vec4 referenceCenter, Geometry dest) { GeometryBuilder gb = this.getGeometryBuilder(); gb.setOrientation(orientation); int count = gb.getPartialDiskIndexCount(slices, loops); int numCoords = 3 * count; float[] verts = new float[numCoords]; float[] norms = new float[numCoords]; gb.makePartialDiskVertices( (float) radii[0], (float) radii[1], slices, loops, (float) start, (float) sweep, verts); this.makePartialDiskTerrainConformant( dc, numCoords, verts, altitude, terrainConformant, referenceCenter); gb.makePartialDiskVertexNormals( (float) radii[0], (float) radii[1], slices, loops, (float) start, (float) sweep, verts, norms); dest.setVertexData(count, verts); dest.setNormalData(count, norms); }
private static boolean collectionToMultiLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof MultiPolygon) && (geom instanceof GeometryCollection) && MultiLineString.class == targetType) { LineString[] geoms = new LineString[geom.getNumGeometries()]; for (int i = 0; i < geom.getNumGeometries(); i++) { geoms[i] = geomBuilder.safeCreateGeometry(LineString.class, geom.getGeometryN(i).getCoordinates()); } result.add(geomBuilder.factory.createMultiLineString(geoms)); return true; } return false; }
private static boolean toLinearRing( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(targetType == LinearRing.class)) return false; ArrayList<Geometry> tmp = new ArrayList<Geometry>(); if (!simpleToLine(geom, LineString.class, tmp)) { if (!collectionToLine(geom, LineString.class, tmp)) { if (!polygonToLine(geom, LineString.class, tmp)) { if (!multiPolygonToLine(geom, LineString.class, tmp)) { return false; } } } } for (Geometry geometry : tmp) { result.add(geomBuilder.safeCreateGeometry(targetType, geometry.getCoordinates())); } return true; }
/** * Create a new Features from the provided coordinates and of the type indicated by geomType * * @param coordCRS The crs of the coordinates provided * @param destinationCRS The desired crs of the geometry * @param type the feature type of the object created * @param coordinates the coordinates that will be used to create the new feature * @param geomType the type of geometry that will be created * @return A new features. * @throws Exception */ public static <T extends Geometry> SimpleFeature createFeature( CoordinateReferenceSystem coordCRS, CoordinateReferenceSystem destinationCRS, SimpleFeatureType type, Coordinate[] coordinates, Class<T> geomType) throws Exception { transform(coordCRS, destinationCRS, coordinates); Object[] attrs = new Object[type.getAttributeCount()]; for (int i = 0; i < attrs.length; i++) { attrs[i] = setDefaultValue(type.getDescriptor(i)); } final SimpleFeature newFeature = SimpleFeatureBuilder.build(type, attrs, null); // Class geomType = type.getDefaultGeometry().getType(); T geom = GeometryBuilder.create().safeCreateGeometry(geomType, coordinates); newFeature.setDefaultGeometry(geom); return newFeature; }
private int getSectionFillIndexCount(int subdivisions) { GeometryBuilder gb = this.getGeometryBuilder(); return 6 * (gb.getSubdivisionPointsVertexCount(subdivisions) - 1); }
private int getSectionVertexCount(int subdivisions) { GeometryBuilder gb = this.getGeometryBuilder(); return 2 * gb.getSubdivisionPointsVertexCount(subdivisions); }
/** * A utility class for playing with features. * * @author jeichar */ public class FeatureUtils { /** * Create a new Features from the provided coordinates and of the type indicated by geomType * * @param coordCRS The crs of the coordinates provided * @param destinationCRS The desired crs of the geometry * @param type the feature type of the object created * @param coordinates the coordinates that will be used to create the new feature * @param geomType the type of geometry that will be created * @return A new features. * @throws Exception */ public static <T extends Geometry> SimpleFeature createFeature( CoordinateReferenceSystem coordCRS, CoordinateReferenceSystem destinationCRS, SimpleFeatureType type, Coordinate[] coordinates, Class<T> geomType) throws Exception { transform(coordCRS, destinationCRS, coordinates); Object[] attrs = new Object[type.getAttributeCount()]; for (int i = 0; i < attrs.length; i++) { attrs[i] = setDefaultValue(type.getDescriptor(i)); } final SimpleFeature newFeature = SimpleFeatureBuilder.build(type, attrs, null); // Class geomType = type.getDefaultGeometry().getType(); T geom = GeometryBuilder.create().safeCreateGeometry(geomType, coordinates); newFeature.setDefaultGeometry(geom); return newFeature; } /** * @param object * @param object2 */ private static Object setDefaultValue(AttributeDescriptor type) { if (type.getDefaultValue() != null) return type.getDefaultValue(); if (Boolean.class.isAssignableFrom(type.getType().getBinding()) || boolean.class.isAssignableFrom(type.getType().getBinding())) return Boolean.valueOf(false); if (String.class.isAssignableFrom(type.getType().getBinding())) return ""; // $NON-NLS-1$ if (Integer.class.isAssignableFrom(type.getType().getBinding())) return Integer.valueOf(0); if (Double.class.isAssignableFrom(type.getType().getBinding())) return Double.valueOf(0); if (Float.class.isAssignableFrom(type.getType().getBinding())) return Float.valueOf(0); if (CodeList.class.isAssignableFrom(type.getType().getBinding())) { return type.getDefaultValue(); } return null; } /** * Transforms coordinates into the layer CRS if nessecary * * @throws Exception */ private static void transform( CoordinateReferenceSystem coordCRS, CoordinateReferenceSystem destinationCRS, Coordinate[] coordinates) throws Exception { if (coordCRS == null || destinationCRS == null) return; MathTransform mt = CRS.findMathTransform(coordCRS, destinationCRS, true); if (mt == null || mt.isIdentity()) return; double[] coords = new double[coordinates.length * 2]; for (int i = 0; i < coordinates.length; i++) { coords[i * 2] = coordinates[i].x; coords[i * 2 + 1] = coordinates[i].y; } mt.transform(coords, 0, coords, 0, coordinates.length); for (int i = 0; i < coordinates.length; i++) { coordinates[i].x = coords[i * 2]; coordinates[i].y = coords[i * 2 + 1]; } } /** * Returns 0 if the features are the same. 1 if the attributes are the same but have different * featureIDs and -1 if attributes are different or are of different featureTypes. * * @param feature1 * @param feature2 * @return */ public static int same(SimpleFeature feature1, SimpleFeature feature2) { if (DataUtilities.compare(feature1.getFeatureType(), feature2.getFeatureType()) != 0) { return -1; } for (int i = 0; i < feature1.getAttributeCount(); i++) { if (feature1.getAttribute(i) == null) { if (feature2.getAttribute(i) != null) return -1; else continue; } if (feature1.getAttribute(i) instanceof Geometry) { Geometry geom1 = (Geometry) feature1.getAttribute(i); if (feature2.getAttribute(i) instanceof Geometry) { Geometry geom2 = (Geometry) feature2.getAttribute(i); if (geom1.equalsExact(geom2)) continue; else return -1; } else return -1; } if (!feature1.getAttribute(i).equals(feature2.getAttribute(i))) return -1; } return feature1.getID().equals(feature2.getID()) ? 0 : 1; } public static Map<String, String> createAttributeMapping( SimpleFeatureType sourceSchema, SimpleFeatureType targetSchema) { Map<String, String> queryAttributes = new HashMap<String, String>(); performDirectMapping(sourceSchema, targetSchema, queryAttributes); mapGeometryAttributes(sourceSchema, targetSchema, queryAttributes); return queryAttributes; } /** Maps the default geometry attribute regardless of whether they are the same type. */ @SuppressWarnings("unchecked") private static void mapGeometryAttributes( SimpleFeatureType sourceSchema, SimpleFeatureType targetSchema, Map<String, String> queryAttributes) { // Now we'll match the geometry on type only. I don't care if it has the same type name. GeometryDescriptor defaultGeometry = targetSchema.getGeometryDescriptor(); if (defaultGeometry == null) { return; } else if (!queryAttributes.containsKey(defaultGeometry.getName())) { // first check source's default geom and see if it matches Class<?> binding = sourceSchema.getGeometryDescriptor().getType().getBinding(); if (defaultGeometry.getType().getBinding().isAssignableFrom(binding)) { queryAttributes.put( defaultGeometry.getName().getLocalPart(), sourceSchema.getGeometryDescriptor().getName().getLocalPart()); } else { // we have to look through all the source attributes looking for a geometry that // matches. boolean found = false; for (int i = 0; i < sourceSchema.getAttributeCount(); i++) { AttributeDescriptor source = sourceSchema.getDescriptor(i); if (defaultGeometry .getType() .getBinding() .isAssignableFrom(source.getType().getBinding())) { queryAttributes.put( defaultGeometry.getName().getLocalPart(), source.getName().getLocalPart()); found = true; break; } } // ok so we're going to have to do some transformations. Match default geometries // then. if (!found) { queryAttributes.put( defaultGeometry.getName().getLocalPart(), sourceSchema.getGeometryDescriptor().getName().getLocalPart()); } } } } /** Maps attributes with the same name and same types to each other. */ @SuppressWarnings("unchecked") private static void performDirectMapping( SimpleFeatureType sourceSchema, SimpleFeatureType targetSchema, Map<String, String> queryAttributes) { for (int i = 0; i < sourceSchema.getAttributeCount(); i++) { AttributeDescriptor source = sourceSchema.getDescriptor(i); for (int j = 0; j < targetSchema.getAttributeCount(); j++) { AttributeDescriptor target = targetSchema.getDescriptor(j); // don't worry about case of attribute name if (target.getName().getLocalPart().equalsIgnoreCase(source.getName().getLocalPart()) && target.getType().getBinding().isAssignableFrom(source.getType().getBinding())) { queryAttributes.put(target.getName().getLocalPart(), source.getName().getLocalPart()); } } } } private static GeometryBuilder geomBuilder = GeometryBuilder.create(); /** * Adapts a collection of features to a FeatureCollection * * @param collection * @return */ public static FeatureCollection<SimpleFeatureType, SimpleFeature> toFeatureCollection( final Collection<SimpleFeature> collection, SimpleFeatureType type) { return new AdaptorFeatureCollection("collection", type) { @Override protected void closeIterator(Iterator arg0) {} @Override protected Iterator openIterator() { return collection.iterator(); } @Override public int size() { return collection.size(); } }; } public static Collection<SimpleFeature> copyFeature( final SimpleFeature source, final SimpleFeatureType destinationSchema, final Map<String, String> attributeMap, final MathTransform mt) { return new AbstractCollection<SimpleFeature>() { public Iterator<SimpleFeature> iterator() { final Map<String, Iterator<? extends Geometry>> geometries = new HashMap<String, Iterator<? extends Geometry>>(); final Object[] attributes = copyAttributes(destinationSchema, source, geometries, attributeMap, mt); return new Iterator<SimpleFeature>() { SimpleFeature next, template; public boolean hasNext() { if (template == null) { try { template = next = SimpleFeatureBuilder.build(destinationSchema, attributes, null); } catch (Exception e) { // try then next one then CorePlugin.log("", e); // $NON-NLS-1$ } return true; } if (geometries.isEmpty()) return false; while (next == null && !geometries.isEmpty()) { try { next = SimpleFeatureBuilder.copy(template); Set<Map.Entry<String, Iterator<? extends Geometry>>> entries = geometries.entrySet(); for (Iterator<Map.Entry<String, Iterator<? extends Geometry>>> iter = entries.iterator(); iter.hasNext(); ) { Map.Entry<String, Iterator<? extends Geometry>> entry = iter.next(); Geometry geom = entry.getValue().next(); next.setAttribute(entry.getKey(), transformGeom(geom, mt)); if (!entry.getValue().hasNext()) iter.remove(); } return true; } catch (Exception e) { // try then next one then CorePlugin.log("", e); // $NON-NLS-1$ } } return false; } public SimpleFeature next() { if (next == null) throw new IndexOutOfBoundsException("No more elements in iterator."); // $NON-NLS-1$ SimpleFeature result = next; next = null; return result; } public void remove() { throw new UnsupportedOperationException(); } }; } public int size() { int size = 0; for (Iterator<SimpleFeature> iter = iterator(); iter.hasNext(); iter.next()) size++; return size; } }; } private static Object[] copyAttributes( SimpleFeatureType destSchema, SimpleFeature source, Map<String, Iterator<? extends Geometry>> geometries, Map<String, String> attributeMap, MathTransform mt) { Object[] attributes = new Object[destSchema.getAttributeCount()]; for (int i = 0; i < attributes.length; i++) { String sourceAttributeName = destSchema.getDescriptor(i).getName().getLocalPart(); String name = attributeMap.get(sourceAttributeName); if (name != null) attributes[i] = source.getAttribute(name); else { attributes[i] = destSchema.getDescriptor(i).getDefaultValue(); } if (attributes[i] instanceof Geometry) { Class<? extends Geometry> geomType = (Class<? extends Geometry>) destSchema.getDescriptor(i).getType().getBinding(); if (!geomType.isAssignableFrom(attributes[i].getClass())) { Collection<? extends Geometry> geom = createCompatibleGeometry((Geometry) attributes[i], geomType); Iterator<? extends Geometry> giter = geom.iterator(); attributes[i] = giter.next(); if (giter.hasNext()) geometries.put(sourceAttributeName, giter); } attributes[i] = transformGeom((Geometry) attributes[i], mt); } } return attributes; } private static Geometry transformGeom(Geometry geom, MathTransform mt) { if (mt != null) { try { return JTS.transform(geom, mt); } catch (TransformException e) { CorePlugin.log("", e); // $NON-NLS-1$ return geom; } } return geom; } private static Collection<? extends Geometry> createCompatibleGeometry( Geometry geom, Class<? extends Geometry> targetType) { Collection<Geometry> result = new ArrayList<Geometry>(); if (nonCollectionToPoint(geom, targetType, result)) return result; else if (collectionToPoint(geom, targetType, result)) return result; else if (nonCollectionToMultiPoint(geom, targetType, result)) return result; else if (collectionToMultiPoint(geom, targetType, result)) return result; else if (simpleToLine(geom, targetType, result)) return result; else if (collectionToLine(geom, targetType, result)) return result; else if (simpleToMultiLine(geom, targetType, result)) return result; else if (collectionToMultiLine(geom, targetType, result)) return result; else if (polygonToMultiLine(geom, targetType, result)) return result; else if (polygonToLine(geom, targetType, result)) return result; else if (multiPolygonToLine(geom, targetType, result)) return result; else if (multiPolygonToMultiLine(geom, targetType, result)) return result; else if (simpleToPolygon(geom, targetType, result)) return result; else if (collectionToPolygon(geom, targetType, result)) return result; else if (multiPolygonToPolygon(geom, targetType, result)) return result; else if (simpleToMultiPolygon(geom, targetType, result)) return result; else if (collectionToMultiPolygon(geom, targetType, result)) return result; else if (polygonToMultiPolygon(geom, targetType, result)) return result; else if (toLinearRing(geom, targetType, result)) return result; throw new IllegalArgumentException( "do not know how transform from " + geom.getClass().getName() + " to " + targetType.getName()); // $NON-NLS-1$ //$NON-NLS-2$ } /** * return true if Geometry is a point and targetType is a point. Result will be populated with the * new point */ private static boolean nonCollectionToPoint( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof GeometryCollection) && Point.class == targetType) { result.add(geom.getCentroid()); return true; } return false; } private static boolean collectionToPoint( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof GeometryCollection && Point.class == targetType) { for (int i = 0; i < geom.getNumGeometries(); i++) { result.add(geom.getGeometryN(i).getCentroid()); } return true; } return false; } private static boolean collectionToMultiPoint( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof GeometryCollection && MultiPoint.class == targetType) { Point[] points = new Point[geom.getNumGeometries()]; for (int i = 0; i < geom.getNumGeometries(); i++) { points[i] = geom.getGeometryN(i).getCentroid(); } result.add(geomBuilder.factory.createMultiPoint(points)); return true; } return false; } private static boolean nonCollectionToMultiPoint( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof GeometryCollection) && MultiPoint.class == targetType) { result.add(geomBuilder.factory.createMultiPoint(geom.getCentroid().getCoordinates())); return true; } return false; } private static boolean simpleToLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof GeometryCollection) && LineString.class == targetType) { result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates())); return true; } return false; } private static boolean collectionToLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof MultiPolygon) && (geom instanceof GeometryCollection) && LineString.class == targetType) { for (int i = 0; i < geom.getNumGeometries(); i++) { result.add( geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates())); } return true; } return false; } private static boolean simpleToMultiLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof GeometryCollection) && MultiLineString.class == targetType) { result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates())); return true; } return false; } private static boolean collectionToMultiLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof MultiPolygon) && (geom instanceof GeometryCollection) && MultiLineString.class == targetType) { LineString[] geoms = new LineString[geom.getNumGeometries()]; for (int i = 0; i < geom.getNumGeometries(); i++) { geoms[i] = geomBuilder.safeCreateGeometry(LineString.class, geom.getGeometryN(i).getCoordinates()); } result.add(geomBuilder.factory.createMultiLineString(geoms)); return true; } return false; } private static boolean simpleToPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof GeometryCollection) && Polygon.class == targetType) { result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates())); return true; } return false; } private static boolean collectionToPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof MultiPolygon) && geom instanceof GeometryCollection && Polygon.class == targetType) { for (int i = 0; i < geom.getNumGeometries(); i++) { result.add( geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates())); } return true; } return false; } private static boolean polygonToLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof Polygon && LineString.class == targetType) { Polygon polygon = (Polygon) geom; result.add( geomBuilder.safeCreateGeometry( LineString.class, polygon.getExteriorRing().getCoordinates())); int i = 0; while (i < polygon.getNumInteriorRing()) { result.add( geomBuilder.safeCreateGeometry( LineString.class, polygon.getInteriorRingN(i).getCoordinates())); i++; } return true; } return false; } private static boolean polygonToMultiLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof Polygon && MultiLineString.class == targetType) { ArrayList<Geometry> tmp = new ArrayList<Geometry>(); if (!polygonToLine(geom, LineString.class, tmp)) throw new RuntimeException( "Huh? multi polygons should only have polygons in them"); //$NON-NLS-1$ result.add(geomBuilder.factory.createMultiLineString(tmp.toArray(new LineString[0]))); return true; } return false; } private static boolean multiPolygonToLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof MultiPolygon && LineString.class == targetType) { for (int i = 0; i < geom.getNumGeometries(); i++) { if (!polygonToLine(geom.getGeometryN(i), targetType, result)) throw new RuntimeException( "Huh? multi polygons should only have polygons in them"); //$NON-NLS-1$ } return true; } return false; } private static boolean multiPolygonToMultiLine( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof MultiPolygon && MultiLineString.class == targetType) { for (int i = 0; i < geom.getNumGeometries(); i++) { if (!polygonToMultiLine(geom.getGeometryN(i), targetType, result)) throw new RuntimeException( "Huh? multi polygons should only have polygons in them, found a " + geom.getGeometryN(i)); // $NON-NLS-1$ } return true; } return false; } private static boolean multiPolygonToPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof MultiPolygon && Polygon.class == targetType) { for (int j = 0; j < geom.getNumGeometries(); j++) { result.add(geom.getGeometryN(j)); } return true; } return false; } private static boolean simpleToMultiPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && !(geom instanceof GeometryCollection) && MultiPolygon.class == targetType) { result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates())); return true; } return false; } private static boolean collectionToMultiPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(geom instanceof Polygon) && geom instanceof GeometryCollection && MultiPolygon.class == targetType) { for (int i = 0; i < geom.getNumGeometries(); i++) { result.add( geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates())); } return true; } return false; } private static boolean polygonToMultiPolygon( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (geom instanceof Polygon && MultiPolygon.class == targetType) { result.add(geomBuilder.factory.createMultiPolygon(new Polygon[] {(Polygon) geom})); return true; } return false; } private static boolean toLinearRing( Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) { if (!(targetType == LinearRing.class)) return false; ArrayList<Geometry> tmp = new ArrayList<Geometry>(); if (!simpleToLine(geom, LineString.class, tmp)) { if (!collectionToLine(geom, LineString.class, tmp)) { if (!polygonToLine(geom, LineString.class, tmp)) { if (!multiPolygonToLine(geom, LineString.class, tmp)) { return false; } } } } for (Geometry geometry : tmp) { result.add(geomBuilder.safeCreateGeometry(targetType, geometry.getCoordinates())); } return true; } public static Set<Identifier> stringToId(FilterFactory fac, String fid) { return stringToId(fac, Collections.singleton(fid)); } public static Set<Identifier> stringToId(FilterFactory fac, Collection<String> fid) { Set<Identifier> ids = new HashSet<Identifier>(); for (String string : fid) { ids.add(fac.featureId(string)); } return ids; } /** * Convert a string to a Id filter * * @param fid the feature id * @return */ @SuppressWarnings("unchecked") public static Filter id(String fid) { FilterFactory factory = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); Set<Identifier> id = stringToId(factory, fid); Id filter = factory.id(id); return filter; } }
private void makePolygon( DrawContext dc, List<LatLon> locations, List<Boolean> edgeFlags, double[] altitudes, boolean[] terrainConformant, boolean enableCaps, int subdivisions, Vec4 referenceCenter, PolygonGeometry dest) { if (locations.size() == 0) return; GeometryBuilder gb = this.getGeometryBuilder(); Vec4[] polyPoints = new Vec4[locations.size() + 1]; Boolean[] polyEdgeFlags = new Boolean[locations.size() + 1]; Matrix[] polyTransform = new Matrix[1]; int polyCount = this.computeCartesianPolygon( dc.getGlobe(), locations, edgeFlags, polyPoints, polyEdgeFlags, polyTransform); // Compute the winding order of the planar cartesian points. If the order is not // counter-clockwise, then // reverse the locations and points ordering. int winding = gb.computePolygonWindingOrder2(0, polyCount, polyPoints); if (winding != GeometryBuilder.COUNTER_CLOCKWISE) { gb.reversePoints(0, polyCount, polyPoints); gb.reversePoints(0, polyCount, polyEdgeFlags); } float[] polyVertices = new float[3 * polyCount]; this.makePolygonVertices(polyCount, polyPoints, polyVertices); int fillDrawMode = GL.GL_TRIANGLES; int outlineDrawMode = GL.GL_LINES; int fillIndexCount = 0; int outlineIndexCount = 0; int vertexCount = 0; GeometryBuilder.IndexedTriangleArray ita = null; fillIndexCount += this.getEdgeFillIndexCount(polyCount, subdivisions); outlineIndexCount += this.getEdgeOutlineIndexCount(polyCount, subdivisions, polyEdgeFlags); vertexCount += this.getEdgeVertexCount(polyCount, subdivisions); if (enableCaps) { ita = gb.tessellatePolygon2(0, polyCount, polyVertices); for (int i = 0; i < subdivisions; i++) { gb.subdivideIndexedTriangleArray(ita); } fillIndexCount += ita.getIndexCount(); vertexCount += ita.getVertexCount(); // Bottom cap isn't drawn if airspace is collapsed. if (!this.isAirspaceCollapsed()) { fillIndexCount += ita.getIndexCount(); vertexCount += ita.getVertexCount(); } } int[] fillIndices = new int[fillIndexCount]; int[] outlineIndices = new int[outlineIndexCount]; float[] vertices = new float[3 * vertexCount]; float[] normals = new float[3 * vertexCount]; int fillIndexPos = 0; int outlineIndexPos = 0; int vertexPos = 0; this.makeEdge( dc, polyCount, polyVertices, polyEdgeFlags, altitudes, terrainConformant, subdivisions, GeometryBuilder.OUTSIDE, polyTransform[0], referenceCenter, fillIndexPos, fillIndices, outlineIndexPos, outlineIndices, vertexPos, vertices, normals); fillIndexPos += this.getEdgeFillIndexCount(polyCount, subdivisions); outlineIndexPos += this.getEdgeOutlineIndexCount(polyCount, subdivisions, polyEdgeFlags); vertexPos += this.getEdgeVertexCount(polyCount, subdivisions); if (enableCaps) { this.makeCap( dc, ita, altitudes[1], terrainConformant[1], GeometryBuilder.OUTSIDE, polyTransform[0], referenceCenter, fillIndexPos, fillIndices, vertexPos, vertices, normals); fillIndexPos += ita.getIndexCount(); vertexPos += ita.getVertexCount(); // Bottom cap isn't drawn if airspace is collapsed. if (!this.isAirspaceCollapsed()) { this.makeCap( dc, ita, altitudes[0], terrainConformant[0], GeometryBuilder.INSIDE, polyTransform[0], referenceCenter, fillIndexPos, fillIndices, vertexPos, vertices, normals); fillIndexPos += ita.getIndexCount(); vertexPos += ita.getVertexCount(); } } dest.getFillIndexGeometry().setElementData(fillDrawMode, fillIndexCount, fillIndices); dest.getOutlineIndexGeometry() .setElementData(outlineDrawMode, outlineIndexCount, outlineIndices); dest.getVertexGeometry().setVertexData(vertexCount, vertices); dest.getVertexGeometry().setNormalData(vertexCount, normals); }