001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package org.geotools.renderer.shape.shapehandler.simple;
018:
019: import java.awt.Rectangle;
020: import java.awt.geom.Point2D;
021: import java.nio.ByteBuffer;
022: import java.util.logging.Logger;
023:
024: import org.geotools.data.shapefile.shp.ShapeHandler;
025: import org.geotools.data.shapefile.shp.ShapeType;
026: import org.geotools.renderer.shape.GeometryHandlerUtilities;
027: import org.geotools.renderer.shape.ScreenMap;
028: import org.geotools.renderer.shape.ShapefileRenderer;
029: import org.geotools.renderer.shape.SimpleGeometry;
030: import org.opengis.referencing.operation.MathTransform;
031: import org.opengis.referencing.operation.TransformException;
032:
033: import com.vividsolutions.jts.geom.Envelope;
034:
035: /**
036: * A ShapeHandler that reads MultiPoint objects from a file. It returns a
037: * SimpleGeometry and decimates all points that map to the same screen location.
038: *
039: * @author jeichar
040: * @since 2.1.x
041: * @source $URL:
042: * http://svn.geotools.org/geotools/branches/2.2.x/ext/shaperenderer/src/org/geotools/renderer/shape/MultiPointHandler.java $
043: */
044: public class MultiPointHandler implements ShapeHandler {
045: private ShapeType type;
046:
047: private Envelope bbox;
048:
049: private MathTransform mt;
050:
051: private ScreenMap screenMap;
052:
053: private double spanx;
054:
055: private double spany;
056:
057: Logger LOGGER = ShapefileRenderer.LOGGER;
058:
059: /**
060: * Create new instance
061: *
062: * @param type
063: * the type of shape.
064: * @param env
065: * the area that is visible. If shape is not in area then skip.
066: * @param mt
067: * the transform to go from data to the envelope (and that should
068: * be used to transform the shape coords)
069: * @param hasOpacity
070: */
071: public MultiPointHandler(ShapeType type, Envelope env,
072: Rectangle screenSize, MathTransform mt, boolean hasOpacity)
073: throws TransformException {
074: if (mt == null) {
075: throw new NullPointerException();
076: }
077:
078: this .type = type;
079: this .bbox = env;
080: this .mt = mt;
081:
082: screenMap = GeometryHandlerUtilities.calculateScreenSize(
083: screenSize, hasOpacity);
084:
085: Point2D span = GeometryHandlerUtilities.calculateSpan(mt, 0, 0);
086: this .spanx = span.getX();
087: this .spany = span.getY();
088: }
089:
090: /**
091: * @see org.geotools.data.shapefile.shp.ShapeHandler#getShapeType()
092: */
093: public ShapeType getShapeType() {
094: return type;
095: }
096:
097: /*
098: * (non-Javadoc)
099: *
100: * @see org.geotools.data.shapefile.shp.ShapeHandler#read(java.nio.ByteBuffer,
101: * org.geotools.data.shapefile.shp.ShapeType)
102: */
103: public Object read(ByteBuffer buffer, ShapeType type) {
104: if (type == ShapeType.NULL) {
105: return null;
106: }
107:
108: // read bounding box
109: Envelope geomBBox = GeometryHandlerUtilities.readBounds(buffer);
110:
111: if (!bbox.intersects(geomBBox)) {
112: return null;
113: }
114:
115: boolean bboxdecimate = geomBBox.getWidth() <= spanx
116: && geomBBox.getHeight() <= spany;
117: int numParts = buffer.getInt();
118:
119: double[][] coords = new double[numParts][];
120: double[][] transformed = new double[numParts][];
121:
122: // if bbox is less than a pixel then decimate the geometry. But
123: // orientation must
124: // remain the same so geometry data must be parsed.
125: if (bboxdecimate) {
126: coords = new double[1][];
127: coords[0] = new double[2];
128: transformed = new double[1][];
129: transformed[0] = new double[2];
130: coords[0][0] = buffer.getDouble();
131: coords[0][1] = buffer.getDouble();
132: try {
133: mt.transform(coords[0], 0, transformed[0], 0, 1);
134: } catch (Exception e) {
135: ShapefileRenderer.LOGGER
136: .severe("could not transform coordinates "
137: + e.getLocalizedMessage());
138: transformed[0] = coords[0];
139: }
140:
141: if (screenMap.get((int) transformed[0][0],
142: (int) transformed[0][1])) {
143: LOGGER.finest("Point already rendered"
144: + transformed[0][0] + " " + transformed[0][1]);
145: return null;
146: }
147: screenMap.set((int) transformed[0][0],
148: (int) transformed[0][1], true);
149: } else {
150:
151: int partsInBBox = 0;
152: for (int part = 0; part < numParts; part++) {
153: coords[part] = new double[2];
154: coords[part][0] = buffer.getDouble();
155: coords[part][1] = buffer.getDouble();
156:
157: if (!bbox.contains(coords[part][0], coords[part][1]))
158: continue;
159:
160: if (!mt.isIdentity()) {
161: try {
162: transformed[partsInBBox] = new double[2];
163: mt.transform(coords[part], 0,
164: transformed[partsInBBox], 0, 1);
165: } catch (Exception e) {
166: ShapefileRenderer.LOGGER
167: .severe("could not transform coordinates "
168: + e.getLocalizedMessage());
169: transformed[partsInBBox] = coords[part];
170: }
171: } else {
172: transformed[partsInBBox] = new double[2];
173: System.arraycopy(coords[part], 0,
174: transformed[partsInBBox], 0, 1);
175: }
176: if (!screenMap.get((int) transformed[partsInBBox][0],
177: (int) transformed[partsInBBox][1]))
178: partsInBBox++;
179: }
180: if (partsInBBox == 0)
181: return null;
182: if (partsInBBox != numParts) {
183: double[][] tmp = new double[partsInBBox][];
184: System.arraycopy(transformed, 0, tmp, 0, partsInBBox);
185: transformed = tmp;
186: }
187: }
188: return createGeometry(type, geomBBox, transformed);
189: }
190:
191: protected Object createGeometry(ShapeType type, Envelope geomBBox,
192: double[][] transformed) {
193: return new SimpleGeometry(type, transformed, geomBBox);
194: }
195:
196: /**
197: * @see org.geotools.data.shapefile.shp.ShapeHandler#write(java.nio.ByteBuffer,
198: * java.lang.Object)
199: */
200: public void write(ByteBuffer buffer, Object geometry) {
201: // This handler doesnt write
202: throw new UnsupportedOperationException(
203: "This handler is only for reading");
204: }
205:
206: /**
207: * @see org.geotools.data.shapefile.shp.ShapeHandler#getLength(java.lang.Object)
208: */
209: public int getLength(Object geometry) {
210: // TODO Auto-generated method stub
211: return 0;
212: }
213:
214: }
|