Revision 41808 trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.file/org.gvsig.fmap.dal.file.shp/src/main/java/org/gvsig/fmap/dal/store/shp/utils/SHPFileWrite.java

View differences:

SHPFileWrite.java
10 10
 *
11 11
 * This program is distributed in the hope that it will be useful,
12 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14
 * GNU General Public License for more details.
15 15
 *
16 16
 * You should have received a copy of the GNU General Public License
17 17
 * along with this program; if not, write to the Free Software
18 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
19
 * MA 02110-1301, USA.
20 20
 *
21 21
 * For any additional information, do not hesitate to contact us
22 22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
......
38 38
import org.slf4j.Logger;
39 39
import org.slf4j.LoggerFactory;
40 40

  
41
public class SHPFileWrite {
41 42

  
43
    private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
44
    private static final Logger logger = LoggerFactory.getLogger(SHPFileWrite.class);
45
    private SHPShape m_shape = null;
46
    private ByteBuffer m_bb = null;
47
    private ByteBuffer m_indexBuffer = null;
48
    private int m_pos = 0;
49
    private int m_offset;
50
    private int m_type = SHP.NULL;
51
    private int m_cnt;
52
    private FileChannel shpChannel;
53
    private FileChannel shxChannel;
54
    private int inconsistenciesInGeometryTypeCounter = 0;
42 55

  
43
/**
44
 * DOCUMENT ME!
45
 *
46
 * @author Vicente Caballero Navarro
47
 */
48
public class SHPFileWrite {
49
	private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
50
	private static final Logger logger = LoggerFactory.getLogger(SHPFileWrite.class);
51
	private SHPShape m_shape = null;
52
	private ByteBuffer m_bb = null;
53
	private ByteBuffer m_indexBuffer = null;
54
	private int m_pos = 0;
55
	private int m_offset;
56
	//	private int m_type;
57
	private int m_cnt;
58
	private FileChannel shpChannel;
59
	private FileChannel shxChannel;
60
//	private double flatness;
56
    public SHPFileWrite(FileChannel shpChannel, FileChannel shxChannel) {
57
        this.shpChannel = shpChannel;
58
        this.shxChannel = shxChannel;
59
    }
61 60

  
62
	/**
63
	 * Crea un nuevo SHPFileWrite.
64
	 *
65
	 * @param shpChannel DOCUMENT ME!
66
	 * @param shxChannel DOCUMENT ME!
67
	 */
68
	public SHPFileWrite(FileChannel shpChannel, FileChannel shxChannel) {
69
		this.shpChannel = shpChannel;
70
		this.shxChannel = shxChannel;
71
	}
61
    /**
62
     * Make sure our buffer is of size.
63
     *
64
     */
65
    private void checkShapeBuffer(int size) {
66
        if ( m_bb.capacity() < size ) {
67
            m_bb = ByteBuffer.allocateDirect(size);
68
        }
69
    }
72 70

  
73
	/**
74
	 * Make sure our buffer is of size.
75
	 *
76
	 * @param size DOCUMENT ME!
77
	 */
78
	private void checkShapeBuffer(int size) {
79
		if (m_bb.capacity() < size) {
80
			m_bb = ByteBuffer.allocateDirect(size);
81
		}
82
	}
71
    /**
72
     * Drain internal buffers into underlying channels.
73
     *
74
     * @throws WriteException
75
     *
76
     */
77
    private void drain() throws WriteException {
78
        m_bb.flip();
79
        m_indexBuffer.flip();
80
        try {
81
            while ( m_bb.remaining() > 0 ) {
82
                shpChannel.write(m_bb);
83
            }
83 84

  
84
	/**
85
	 * Drain internal buffers into underlying channels.
86
	 * @throws WriteException
87
	 *
88
	 * @throws IOException DOCUMENT ME!
89
	 */
90
	private void drain() throws WriteException {
91
		m_bb.flip();
92
		m_indexBuffer.flip();
93
		try{
94
		while (m_bb.remaining() > 0) {
95
			shpChannel.write(m_bb);
96
		}
85
            while ( m_indexBuffer.remaining() > 0 ) {
86
                shxChannel.write(m_indexBuffer);
87
            }
88
        } catch (IOException e) {
89
            throw new WriteException("SHP File Write Drain", e);
90
        }
91
        m_bb.flip().limit(m_bb.capacity());
92
        m_indexBuffer.flip().limit(m_indexBuffer.capacity());
93
    }
97 94

  
98
		while (m_indexBuffer.remaining() > 0) {
99
			shxChannel.write(m_indexBuffer);
100
		}
101
		}catch (IOException e) {
102
			throw new WriteException("SHP File Write Drain", e);
103
		}
104
		m_bb.flip().limit(m_bb.capacity());
105
		m_indexBuffer.flip().limit(m_indexBuffer.capacity());
106
	}
95
    private void allocateBuffers() {
96
        m_bb = ByteBuffer.allocateDirect(16 * 1024);
97
        m_indexBuffer = ByteBuffer.allocateDirect(100);
98
    }
107 99

  
108
	/**
109
	 * DOCUMENT ME!
110
	 */
111
	private void allocateBuffers() {
112
		m_bb = ByteBuffer.allocateDirect(16 * 1024);
113
		m_indexBuffer = ByteBuffer.allocateDirect(100);
114
	}
100
    /**
101
     * Close the underlying Channels.
102
     */
103
    public void close() throws WriteException {
104
        try {
105
            shpChannel.close();
106
            shxChannel.close();
107
        } catch (IOException e) {
108
            throw new WriteException("SHP File Write Close", e);
109
        }
110
        shpChannel = null;
111
        shxChannel = null;
112
        m_shape = null;
115 113

  
116
	/**
117
	 * Close the underlying Channels.
118
	 */
119
	public void close() throws WriteException {
120
		try {
121
			shpChannel.close();
122
			shxChannel.close();
123
		} catch (IOException e) {
124
			throw new WriteException("SHP File Write Close", e);
125
		}
126
		shpChannel = null;
127
		shxChannel = null;
128
		m_shape = null;
114
        if ( m_indexBuffer instanceof ByteBuffer ) {
115
            if ( m_indexBuffer != null ) {
116
                ///NIOUtilities.clean(m_indexBuffer);
117
            }
118
        }
129 119

  
130
		if (m_indexBuffer instanceof ByteBuffer) {
131
			if (m_indexBuffer != null) {
132
				///NIOUtilities.clean(m_indexBuffer);
133
			}
134
		}
120
        if ( m_indexBuffer instanceof ByteBuffer ) {
121
            if ( m_indexBuffer != null ) {
122
                ///NIOUtilities.clean(m_bb);
123
            }
124
        }
135 125

  
136
		if (m_indexBuffer instanceof ByteBuffer) {
137
			if (m_indexBuffer != null) {
138
				///NIOUtilities.clean(m_bb);
139
			}
140
		}
126
        m_indexBuffer = null;
127
        m_bb = null;
128
    }
141 129

  
142
		m_indexBuffer = null;
143
		m_bb = null;
144
	}
130
    public void write(Geometry[] geometries, int type)
131
            throws WriteException {
132
        m_shape = SHP.create(type);
133
        writeHeaders(geometries, type);
145 134

  
146
	/**
147
	 * DOCUMENT ME!
148
	 *
149
	 * @param geometries DOCUMENT ME!
150
	 * @param type DOCUMENT ME!
151
	 *
152
	 */
153
	public void write(Geometry[] geometries, int type)
154
			throws WriteException {
155
		m_shape = SHP.create(type);
156
//		m_shape.setFlatness(flatness);
157
		writeHeaders(geometries, type);
135
        m_pos = m_bb.position();
158 136

  
159
		m_pos = m_bb.position();
137
        for ( int i = 0, ii = geometries.length; i < ii; i++ ) {
138
            writeGeometry(geometries[i]);
139
        }
160 140

  
161
		for (int i = 0, ii = geometries.length; i < ii; i++) {
162
			writeGeometry(geometries[i]);
163
		}
141
        close();
142
    }
164 143

  
165
		close();
166
	}
144
    private void writeHeaders(Geometry[] geometries, int type)
145
            throws WriteException {
146
        this.m_type = type;
147
        this.inconsistenciesInGeometryTypeCounter = 0;
167 148

  
168
	/**
169
	 * DOCUMENT ME!
170
	 *
171
	 * @param geometries DOCUMENT ME!
172
	 * @param type DOCUMENT ME!
173
	 * @throws WriteException
174
	 *
175
	 */
176
	private void writeHeaders(Geometry[] geometries, int type)
177
			throws WriteException {
178
		int fileLength = 100;		
179
		Envelope envelope = null;
180
		try {
181
		    envelope = geomManager.createEnvelope(SUBTYPES.GEOM2D);
149
        int fileLength = 100;
150
        Envelope envelope = null;
151
        try {
152
            envelope = geomManager.createEnvelope(SUBTYPES.GEOM2D);
182 153
        } catch (CreateEnvelopeException e) {
183 154
            logger.error("Error creating the envelope", e);
184 155
        }
185 156

  
186
		for (int i = geometries.length - 1; i >= 0; i--) {
187
			Geometry fgeometry = geometries[i];
188
			m_shape.obtainsPoints(fgeometry);
189
			int size = m_shape.getLength(fgeometry) + 8;
190
			fileLength += size;
191
			envelope.add(fgeometry.getEnvelope());			
192
		}
157
        for ( int i = geometries.length - 1; i >= 0; i-- ) {
158
            Geometry fgeometry = geometries[i];
159
            m_shape.obtainsPoints(fgeometry);
160
            int size = m_shape.getLength(fgeometry) + 8;
161
            fileLength += size;
162
            envelope.add(fgeometry.getEnvelope());
163
        }
193 164

  
194
		writeHeaders(envelope, type, geometries.length, fileLength);
195
	}
165
        writeHeaders(envelope, type, geometries.length, fileLength);
196 166

  
197
	/**
198
	 * Writes shape header (100 bytes)
199
	 *
200
	 * @param bounds DOCUMENT ME!
201
	 * @param type DOCUMENT ME!
202
	 * @param numberOfGeometries DOCUMENT ME!
203
	 * @param fileLength DOCUMENT ME!
204
	 */
205
	public void writeHeaders(Envelope bounds, int type,
206
		int numberOfGeometries,
207
			int fileLength) throws WriteException {
208
		/*try {
209
		   handler = type.getShapeHandler();
210
		   } catch (ShapefileException se) {
211
		     throw new RuntimeException("unexpected Exception",se);
212
		   }
213
		 */
214
		if (m_bb == null) {
215
			allocateBuffers();
216
		}
217
		// Posicionamos al principio.
218
		m_bb.position(0);
219
		m_indexBuffer.position(0);
167
    }
220 168

  
221
		ShapeFileHeader2 header = new ShapeFileHeader2();
169
    /**
170
     * Writes shape header (100 bytes)
171
     */
172
    public void writeHeaders(Envelope bounds, int type,
173
            int numberOfGeometries,
174
            int fileLength) throws WriteException {
222 175

  
223
		header.write(m_bb, type, numberOfGeometries, fileLength / 2,
224
			bounds
225
				.getMinimum(0), bounds.getMinimum(1), bounds.getMaximum(0),
226
			bounds.getMaximum(1), 0, 0, 0, 0);
176
        this.m_type = type;
177
        this.inconsistenciesInGeometryTypeCounter = 0;
227 178

  
228
		header.write(m_indexBuffer, type, numberOfGeometries,
229
			50 + (4 * numberOfGeometries), bounds.getMinimum(0), bounds.getMinimum(1),
230
			bounds.getMaximum(0), bounds.getMaximum(1), 0, 0, 0, 0);
179
        if ( m_bb == null ) {
180
            allocateBuffers();
181
        }
182
        // Posicionamos al principio.
183
        m_bb.position(0);
184
        m_indexBuffer.position(0);
231 185

  
232
		m_offset = 50;
233
//		m_type = type;
234
		m_cnt = 0;
186
        ShapeFileHeader2 header = new ShapeFileHeader2();
235 187

  
236
		try {
237
			shpChannel.position(0);
238
			shxChannel.position(0);
239
		} catch (IOException e) {
240
			throw new WriteException("SHP File Write Headers", e);
241
		}
242
		drain();
243
	}
244
	public int writeIGeometry(Geometry g) throws WriteException {
245
            if( g==null ) {
246
                m_shape = SHP.create(0);
247
            } else {
248
		int shapeType = getShapeType(g.getType(), g.getGeometryType().getSubType());
249
		m_shape = SHP.create(shapeType);
250
//		m_shape.setFlatness(flatness);
251
		// System.out.println("writeIGeometry: type="+ g.getType());
188
        header.write(m_bb, type, numberOfGeometries, fileLength / 2,
189
                bounds
190
                .getMinimum(0), bounds.getMinimum(1), bounds.getMaximum(0),
191
                bounds.getMaximum(1), 0, 0, 0, 0);
192

  
193
        header.write(m_indexBuffer, type, numberOfGeometries,
194
                50 + (4 * numberOfGeometries), bounds.getMinimum(0), bounds.getMinimum(1),
195
                bounds.getMaximum(0), bounds.getMaximum(1), 0, 0, 0, 0);
196

  
197
        m_offset = 50;
198
        m_cnt = 0;
199

  
200
        try {
201
            shpChannel.position(0);
202
            shxChannel.position(0);
203
        } catch (IOException e) {
204
            throw new WriteException("SHP File Write Headers", e);
205
        }
206
        drain();
207
    }
208

  
209
    public int writeIGeometry(Geometry g) throws WriteException {
210
        if ( g == null ) {
211
            m_shape = SHP.create(0);
212
        } else {
213
            int shapeType = getShapeType(g.getType(), g.getGeometryType().getSubType());
214
            m_shape = SHP.create(shapeType);
215
        }
216
        return writeGeometry(g);
217
    }
218

  
219
    /**
220
     * Writes a single Geometry.
221
     *
222
     * @param g
223
     * @return the position of buffer (after the last geometry, it will allow
224
     * you to write the file size in the header.
225
     */
226
    public synchronized int writeGeometry(Geometry g)
227
            throws WriteException {
228
        if ( m_shape.getShapeType() != this.m_type ) {
229
            if ( this.inconsistenciesInGeometryTypeCounter++ < 10 ) {
230
                logger.warn("Saving a geometry of type '" + SHP.getTypeName(m_shape.getShapeType()) + "' in a shape of type '" + SHP.getTypeName(this.m_type) + "'.");
231
            } else if ( this.inconsistenciesInGeometryTypeCounter++ < 11 ) {
232
                logger.warn("Too many warnings. Saving a geometry of type '" + SHP.getTypeName(m_shape.getShapeType()) + "' in a shape of type '" + SHP.getTypeName(this.m_type) + "'.");
252 233
            }
253
            return writeGeometry(g);
254
	}
234
        }
235
       
236
        if ( m_bb == null ) {
237
            allocateBuffers();
238
            m_offset = 50;
239
            m_cnt = 0;
255 240

  
256
	/**
257
	 * Writes a single Geometry.
258
	 *
259
	 * @param g
260
	 * @return the position of buffer (after the last geometry, it will allow you to
261
	 * write the file size in the header.
262
	 */
263
	public synchronized int writeGeometry(Geometry g)
264
			throws WriteException {
265
		if (m_bb == null) {
266
			allocateBuffers();
267
			m_offset = 50;
268
			m_cnt = 0;
241
            try {
242
                shpChannel.position(0);
243
                shxChannel.position(0);
244
            } catch (IOException e) {
245
                throw new WriteException("SHP File Write", e);
246
            }
247
        }
269 248

  
270
			try {
271
				shpChannel.position(0);
272
				shxChannel.position(0);
273
			} catch (IOException e) {
274
				throw new WriteException("SHP File Write", e);
275
			}
276
			// throw new IOException("Must write headers first");
277
		}
249
        m_pos = m_bb.position();
250
        m_shape.obtainsPoints(g);
251
        int length = m_shape.getLength(g);
278 252

  
279
		m_pos = m_bb.position();
280
		m_shape.obtainsPoints(g);
281
		int length = m_shape.getLength(g);
253
        // must allocate enough for shape + header (2 ints)
254
        checkShapeBuffer(length + 8);
282 255

  
283
		// must allocate enough for shape + header (2 ints)
284
		checkShapeBuffer(length + 8);
256
        length /= 2;
285 257

  
286
		length /= 2;
258
        m_bb.order(ByteOrder.BIG_ENDIAN);
259
        m_bb.putInt(++m_cnt);
260
        m_bb.putInt(length);
261
        m_bb.order(ByteOrder.LITTLE_ENDIAN);
262
        m_bb.putInt(m_shape.getShapeType());
263
        m_shape.write(m_bb, g);
287 264

  
288
		m_bb.order(ByteOrder.BIG_ENDIAN);
289
		m_bb.putInt(++m_cnt);
290
		m_bb.putInt(length);
291
		m_bb.order(ByteOrder.LITTLE_ENDIAN);
292
		m_bb.putInt(m_shape.getShapeType());
293
		m_shape.write(m_bb, g);
265
        m_pos = m_bb.position();
294 266

  
295
		///assert (length * 2 == (m_bb.position() - m_pos) - 8);
296
		m_pos = m_bb.position();
267
        // write to the shx
268
        m_indexBuffer.putInt(m_offset);
269
        m_indexBuffer.putInt(length);
270
        m_offset += (length + 4);
271
        drain();
297 272

  
298
		// write to the shx
299
		m_indexBuffer.putInt(m_offset);
300
		m_indexBuffer.putInt(length);
301
		m_offset += (length + 4);
302
		drain();
273
        return m_pos; // Devolvemos hasta donde hemos escrito
274
    }
303 275

  
304
		///assert(m_bb.position() == 0);
305
		return m_pos; // Devolvemos hasta donde hemos escrito
306
	}
276
    /**
277
     * Returns a shapeType compatible with shapeFile constants from a gvSIG's
278
     * IGeometry type
279
     *
280
     * @param geometryType
281
     * @return a shapeType compatible with shapeFile constants from a gvSIG's
282
     * IGeometry type
283
     */
284
    public int getShapeType(int geometryType, int geometrySubType) {
307 285

  
308
	/**
309
	 * Returns a shapeType compatible with shapeFile constants from a gvSIG's IGeometry type
310
	 * @param geometryType
311
	 * @return a shapeType compatible with shapeFile constants from a gvSIG's IGeometry type
312
	 */
313
	public int getShapeType(int geometryType, int geometrySubType) {
286
        if ( geometrySubType == Geometry.SUBTYPES.GEOM3D ) {
287
            switch (geometryType) {
288
            case Geometry.TYPES.NULL:
289
                return SHP.NULL;
314 290

  
315
		if (geometrySubType == Geometry.SUBTYPES.GEOM3D){
316
			switch (geometryType) {
317
                        case Geometry.TYPES.NULL:
318
                                return SHP.NULL;
319
                            
320
			case Geometry.TYPES.POINT:
321
				return SHP.POINT3D;
291
            case Geometry.TYPES.POINT:
292
                return SHP.POINT3D;
322 293

  
323
			case Geometry.TYPES.CURVE:
324
			case Geometry.TYPES.MULTICURVE:
325
			case Geometry.TYPES.ELLIPSE:
326
			case Geometry.TYPES.CIRCLE:
327
			case Geometry.TYPES.ARC:
328
			case Geometry.TYPES.SPLINE: 
329
				return SHP.POLYLINE3D;
294
            case Geometry.TYPES.CURVE:
295
            case Geometry.TYPES.MULTICURVE:
296
            case Geometry.TYPES.ELLIPSE:
297
            case Geometry.TYPES.CIRCLE:
298
            case Geometry.TYPES.ARC:
299
            case Geometry.TYPES.SPLINE:
300
                return SHP.POLYLINE3D;
330 301

  
331
			case Geometry.TYPES.SURFACE:
332
			case Geometry.TYPES.MULTISURFACE:
333
				return SHP.POLYGON3D;
302
            case Geometry.TYPES.SURFACE:
303
            case Geometry.TYPES.MULTISURFACE:
304
                return SHP.POLYGON3D;
334 305

  
335
			case Geometry.TYPES.MULTIPOINT:
336
				return SHP.MULTIPOINT3D; //TODO falta aclarar cosas aqu?.
337
		}
306
            case Geometry.TYPES.MULTIPOINT:
307
                return SHP.MULTIPOINT3D; //TODO falta aclarar cosas aqu?.
308
            }
338 309

  
339
		}else{
340
			switch (geometryType) {
341
				case Geometry.TYPES.POINT:
342
					return SHP.POINT2D;
310
        } else {
311
            switch (geometryType) {
312
            case Geometry.TYPES.POINT:
313
                return SHP.POINT2D;
343 314

  
344
				case Geometry.TYPES.CURVE:
345
				case Geometry.TYPES.MULTICURVE:
346
				case Geometry.TYPES.ELLIPSE:
347
				case Geometry.TYPES.CIRCLE:
348
				case Geometry.TYPES.ARC:
349
				case Geometry.TYPES.SPLINE: 
350
					return SHP.POLYLINE2D;
315
            case Geometry.TYPES.CURVE:
316
            case Geometry.TYPES.MULTICURVE:
317
            case Geometry.TYPES.ELLIPSE:
318
            case Geometry.TYPES.CIRCLE:
319
            case Geometry.TYPES.ARC:
320
            case Geometry.TYPES.SPLINE:
321
                return SHP.POLYLINE2D;
351 322

  
352
				case Geometry.TYPES.SURFACE:
353
				case Geometry.TYPES.MULTISURFACE:
354
					return SHP.POLYGON2D;
323
            case Geometry.TYPES.SURFACE:
324
            case Geometry.TYPES.MULTISURFACE:
325
                return SHP.POLYGON2D;
355 326

  
356
				case Geometry.TYPES.MULTIPOINT:
357
					return SHP.MULTIPOINT2D; //TODO falta aclarar cosas aqu?.
358
			}
359
		}
360
			return SHP.NULL;
361
		}
327
            case Geometry.TYPES.MULTIPOINT:
328
                return SHP.MULTIPOINT2D; //TODO falta aclarar cosas aqu?.
329
            }
330
        }
331
        return SHP.NULL;
332
    }
362 333
}

Also available in: Unified diff