1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the CPCIDSKVectorSegment class.
4 : *
5 : ******************************************************************************
6 : * Copyright (c) 2009
7 : * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
8 : *
9 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #include "pcidsk_exception.h"
29 : #include "core/pcidsk_utils.h"
30 : #include "segment/cpcidskvectorsegment.h"
31 : #include <cassert>
32 : #include <cstring>
33 :
34 : using namespace PCIDSK;
35 :
36 : /* -------------------------------------------------------------------- */
37 : /* Size of a block in the record/vertice block tables. This is */
38 : /* determined by the PCIDSK format and may not be changed. */
39 : /* -------------------------------------------------------------------- */
40 : static const int block_page_size = 8192;
41 :
42 : /* -------------------------------------------------------------------- */
43 : /* Size of one page of loaded shapeids. This is not related to */
44 : /* the file format, and may be changed to alter the number of */
45 : /* shapeid pointers kept in RAM at one time from the shape */
46 : /* index. */
47 : /* -------------------------------------------------------------------- */
48 : static const int shapeid_page_size = 1024;
49 :
50 : const int CPCIDSKVectorSegment::sec_raw = 0;
51 : const int CPCIDSKVectorSegment::sec_vert = 1;
52 : const int CPCIDSKVectorSegment::sec_record = 2;
53 :
54 : /************************************************************************/
55 : /* CPCIDSKVectorSegment() */
56 : /************************************************************************/
57 :
58 0 : CPCIDSKVectorSegment::CPCIDSKVectorSegment( PCIDSKFile *file, int segment,
59 : const char *segment_pointer )
60 0 : : CPCIDSKSegment( file, segment, segment_pointer )
61 :
62 : {
63 0 : base_initialized = false;
64 :
65 0 : last_shapes_id = NullShapeId;
66 0 : last_shapes_index = -1;
67 :
68 0 : raw_loaded_data_offset = 0;
69 0 : vert_loaded_data_offset = 0;
70 0 : record_loaded_data_offset = 0;
71 :
72 0 : shapeid_map_active = false;
73 0 : shapeid_pages_certainly_mapped = -1;
74 0 : }
75 :
76 : /************************************************************************/
77 : /* ~CPCIDSKVectorSegment() */
78 : /************************************************************************/
79 :
80 0 : CPCIDSKVectorSegment::~CPCIDSKVectorSegment()
81 :
82 : {
83 0 : }
84 :
85 : /************************************************************************/
86 : /* Initialize() */
87 : /* */
88 : /* Initialize minimum information from the vector segment */
89 : /* header. We defer this till an actual vector related action */
90 : /* is taken. */
91 : /************************************************************************/
92 :
93 0 : void CPCIDSKVectorSegment::Initialize()
94 :
95 : {
96 0 : if( base_initialized )
97 0 : return;
98 :
99 0 : base_initialized = true;
100 :
101 : // vector segment data is always big endian.
102 :
103 0 : needs_swap = !BigEndianSystem();
104 :
105 : /* -------------------------------------------------------------------- */
106 : /* Check fixed portion of the header to ensure this is a V6 */
107 : /* style vector segment. */
108 : /* -------------------------------------------------------------------- */
109 : static const unsigned char magic[24] =
110 : { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
111 : 0, 0, 0, 21, 0, 0, 0, 4, 0, 0, 0, 19, 0, 0, 0, 69 };
112 :
113 0 : if( memcmp( GetData( sec_raw, 0, NULL, 24 ), magic, 24 ) != 0 )
114 : {
115 0 : ThrowPCIDSKException( "Unexpected vector header values, possibly it is not a V6 vector segment?" );
116 : }
117 :
118 : /* -------------------------------------------------------------------- */
119 : /* Load section offsets. */
120 : /* -------------------------------------------------------------------- */
121 0 : memcpy( section_offsets, GetData( sec_raw, 72, NULL, 16 ), 16 );
122 0 : if( needs_swap )
123 0 : SwapData( section_offsets, 4, 4 );
124 :
125 : /* -------------------------------------------------------------------- */
126 : /* Load the field definitions. */
127 : /* -------------------------------------------------------------------- */
128 0 : ShapeField work_value;
129 : int field_count, i;
130 :
131 0 : uint32 next_off = section_offsets[2];
132 :
133 0 : next_off = ReadField( next_off, work_value, FieldTypeInteger, sec_raw );
134 0 : field_count = work_value.GetValueInteger();
135 :
136 0 : for( i = 0; i < field_count; i++ )
137 : {
138 0 : next_off = ReadField( next_off, work_value, FieldTypeString, sec_raw );
139 0 : field_names.push_back( work_value.GetValueString() );
140 :
141 0 : next_off = ReadField( next_off, work_value, FieldTypeString, sec_raw );
142 0 : field_descriptions.push_back( work_value.GetValueString() );
143 :
144 0 : next_off = ReadField( next_off, work_value, FieldTypeInteger, sec_raw );
145 0 : field_types.push_back( (ShapeFieldType) work_value.GetValueInteger() );
146 :
147 0 : next_off = ReadField( next_off, work_value, FieldTypeString, sec_raw );
148 0 : field_formats.push_back( work_value.GetValueString() );
149 :
150 0 : next_off = ReadField( next_off, work_value, field_types[i], sec_raw );
151 0 : field_defaults.push_back( work_value );
152 : }
153 :
154 : /* -------------------------------------------------------------------- */
155 : /* Fetch the vertex block basics. */
156 : /* -------------------------------------------------------------------- */
157 0 : next_off = section_offsets[3];
158 0 : vertex_block_initialized = false;
159 :
160 0 : memcpy( &vertex_block_count, GetData(sec_raw,next_off,NULL,4), 4);
161 0 : memcpy( &vertex_bytes, GetData(sec_raw,next_off+4,NULL,4), 4);
162 :
163 0 : if( needs_swap )
164 : {
165 0 : SwapData( &vertex_block_count, 4, 1 );
166 0 : SwapData( &vertex_bytes, 4, 1 );
167 : }
168 :
169 0 : next_off += 8 + 4 * vertex_block_count;
170 :
171 : /* -------------------------------------------------------------------- */
172 : /* Fetch the record block basics. */
173 : /* -------------------------------------------------------------------- */
174 0 : record_block_initialized = false;
175 :
176 0 : memcpy( &record_block_count, GetData(sec_raw,next_off,NULL,4), 4);
177 0 : memcpy( &record_bytes, GetData(sec_raw,next_off+4,NULL,4), 4);
178 :
179 0 : if( needs_swap )
180 : {
181 0 : SwapData( &record_block_count, 4, 1 );
182 0 : SwapData( &record_bytes, 4, 1 );
183 : }
184 :
185 0 : next_off += 8 + 4 * record_block_count;
186 :
187 : /* -------------------------------------------------------------------- */
188 : /* Fetch the shapeid basics. */
189 : /* -------------------------------------------------------------------- */
190 0 : memcpy( &shape_count, GetData(sec_raw,next_off,NULL,4), 4);
191 0 : if( needs_swap )
192 0 : SwapData( &shape_count, 4, 1 );
193 :
194 0 : next_off += 4;
195 0 : shape_index_byte_offset = next_off;
196 :
197 0 : shape_index_start = 0;
198 : }
199 :
200 : /************************************************************************/
201 : /* ReadField() */
202 : /* */
203 : /* Read a value from the indicated offset in a section of the */
204 : /* vector segment, and place the value into a ShapeField */
205 : /* structure based on the passed in field type. */
206 : /************************************************************************/
207 :
208 0 : uint32 CPCIDSKVectorSegment::ReadField( uint32 offset, ShapeField& field,
209 : ShapeFieldType field_type,
210 : int section )
211 :
212 : {
213 0 : switch( field_type )
214 : {
215 : case FieldTypeInteger:
216 : {
217 : int32 value;
218 0 : memcpy( &value, GetData( section, offset, NULL, 4), 4 );
219 0 : if( needs_swap )
220 0 : SwapData( &value, 4, 1 );
221 0 : field.SetValue( value );
222 0 : return offset + 4;
223 : }
224 :
225 : case FieldTypeFloat:
226 : {
227 : float value;
228 0 : memcpy( &value, GetData( section, offset, NULL, 4), 4 );
229 0 : if( needs_swap )
230 0 : SwapData( &value, 4, 1 );
231 0 : field.SetValue( value );
232 0 : return offset + 4;
233 : }
234 :
235 : case FieldTypeDouble:
236 : {
237 : double value;
238 0 : memcpy( &value, GetData( section, offset, NULL, 8), 8 );
239 0 : if( needs_swap )
240 0 : SwapData( &value, 8, 1 );
241 0 : field.SetValue( value );
242 0 : return offset + 8;
243 : }
244 :
245 : case FieldTypeString:
246 : {
247 : int available;
248 0 : char *srcdata = GetData( section, offset, &available, 1 );
249 :
250 : // Simple case -- all initially available.
251 0 : int string_len = 0;
252 :
253 0 : while( srcdata[string_len] != '\0' && available - string_len > 0 )
254 0 : string_len++;
255 :
256 0 : if( string_len < available && srcdata[string_len] == '\0' )
257 : {
258 0 : std::string value( srcdata, string_len );
259 0 : field.SetValue( value );
260 0 : return offset + string_len + 1;
261 : }
262 :
263 0 : std::string value;
264 :
265 0 : while( *srcdata != '\0' )
266 : {
267 0 : value += *(srcdata++);
268 0 : offset++;
269 0 : available--;
270 0 : if( available == 0 )
271 0 : srcdata = GetData( section, offset, &available, 1 );
272 : }
273 :
274 0 : field.SetValue( value );
275 0 : return offset+1;
276 : }
277 :
278 : case FieldTypeCountedInt:
279 : {
280 0 : std::vector<int32> value;
281 : int32 count;
282 0 : char *srcdata = GetData( section, offset, NULL, 4 );
283 0 : memcpy( &count, srcdata, 4 );
284 0 : if( needs_swap )
285 0 : SwapData( &count, 4, 1 );
286 :
287 0 : value.resize( count );
288 0 : memcpy( &(value[0]), GetData(section,offset+4,NULL,4*count), 4*count );
289 0 : if( needs_swap )
290 0 : SwapData( &(value[0]), 4, count );
291 0 : field.SetValue( value );
292 0 : return offset + 4 + 4*count;
293 : }
294 :
295 : default:
296 0 : assert( 0 );
297 : return offset;
298 : }
299 : }
300 :
301 : /************************************************************************/
302 : /* GetData() */
303 : /************************************************************************/
304 :
305 0 : char *CPCIDSKVectorSegment::GetData( int section, uint32 offset,
306 : int *bytes_available, int min_bytes )
307 :
308 : {
309 0 : if( min_bytes == 0 )
310 0 : min_bytes = 1;
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Select the section to act on. */
314 : /* -------------------------------------------------------------------- */
315 : PCIDSKBuffer *pbuf;
316 : uint32 *pbuf_offset;
317 :
318 0 : if( section == sec_raw )
319 : {
320 0 : pbuf = &raw_loaded_data;
321 0 : pbuf_offset = &raw_loaded_data_offset;
322 : }
323 0 : else if( section == sec_vert )
324 : {
325 0 : pbuf = &vert_loaded_data;
326 0 : pbuf_offset = &vert_loaded_data_offset;
327 : }
328 0 : else if( section == sec_record )
329 : {
330 0 : pbuf = &record_loaded_data;
331 0 : pbuf_offset = &record_loaded_data_offset;
332 : }
333 :
334 : /* -------------------------------------------------------------------- */
335 : /* If the desired data is not within our loaded section, reload */
336 : /* one or more blocks around the request. */
337 : /* -------------------------------------------------------------------- */
338 0 : if( offset < *pbuf_offset
339 : || offset+min_bytes > *pbuf_offset + pbuf->buffer_size )
340 : {
341 : // read whole 8K blocks around the target region.
342 0 : uint32 load_offset = offset - (offset % block_page_size);
343 0 : int size = (offset + min_bytes - load_offset + block_page_size - 1);
344 :
345 0 : size -= (size % block_page_size);
346 :
347 0 : *pbuf_offset = load_offset;
348 0 : pbuf->SetSize( size );
349 :
350 : ReadSecFromFile( section, pbuf->buffer,
351 0 : load_offset / block_page_size, size / block_page_size );
352 : }
353 :
354 : /* -------------------------------------------------------------------- */
355 : /* Return desired info. */
356 : /* -------------------------------------------------------------------- */
357 0 : if( bytes_available != NULL )
358 0 : *bytes_available = *pbuf_offset + pbuf->buffer_size - offset;
359 :
360 0 : return pbuf->buffer + offset - *pbuf_offset;
361 : }
362 :
363 : /************************************************************************/
364 : /* ReadSecFromFile() */
365 : /* */
366 : /* Read one or more blocks from the desired "section" of the */
367 : /* segment data, going through the block pointer map for */
368 : /* vect/record sections. */
369 : /************************************************************************/
370 :
371 0 : void CPCIDSKVectorSegment::ReadSecFromFile( int section, char *buffer,
372 : int block_offset,
373 : int block_count )
374 :
375 : {
376 : /* -------------------------------------------------------------------- */
377 : /* Raw is a simple case, directly gulp. */
378 : /* -------------------------------------------------------------------- */
379 0 : if( section == sec_raw )
380 : {
381 0 : ReadFromFile( buffer, block_offset*block_page_size, block_count*block_page_size );
382 0 : return;
383 : }
384 :
385 : /* -------------------------------------------------------------------- */
386 : /* Load vertex block map if needed. */
387 : /* -------------------------------------------------------------------- */
388 0 : if( section == sec_vert && !vertex_block_initialized )
389 : {
390 0 : vertex_block_index.resize( vertex_block_count );
391 : ReadFromFile( &(vertex_block_index[0]),
392 0 : section_offsets[3] + 8,
393 0 : 4 * vertex_block_count );
394 0 : if( needs_swap )
395 0 : SwapData( &(vertex_block_index[0]), 4, vertex_block_count );
396 :
397 0 : vertex_block_initialized = true;
398 : }
399 :
400 : /* -------------------------------------------------------------------- */
401 : /* Load record block map if needed. */
402 : /* -------------------------------------------------------------------- */
403 0 : if( section == sec_record && !record_block_initialized )
404 : {
405 0 : record_block_index.resize( record_block_count );
406 : ReadFromFile( &(record_block_index[0]),
407 0 : section_offsets[3] + 16 + 4*vertex_block_count,
408 0 : 4 * record_block_count );
409 0 : if( needs_swap )
410 0 : SwapData( &(record_block_index[0]), 4, record_block_count );
411 :
412 0 : record_block_initialized = true;
413 : }
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* Process one 8K block at a time in case they are discontigous */
417 : /* which they often are. */
418 : /* -------------------------------------------------------------------- */
419 : int i;
420 : std::vector<uint32> *block_map;
421 :
422 0 : if( section == sec_vert )
423 0 : block_map = &vertex_block_index;
424 : else
425 0 : block_map = &record_block_index;
426 :
427 0 : assert( block_count + block_offset <= (int) block_map->size() );
428 :
429 0 : for( i = 0; i < block_count; i++ )
430 : {
431 : ReadFromFile( buffer + i * block_page_size,
432 : block_page_size * (*block_map)[block_offset+i],
433 0 : block_page_size );
434 : }
435 : }
436 :
437 : /************************************************************************/
438 : /* IndexFromShapeId() */
439 : /* */
440 : /* Translate a shapeid into a shape index. Several mechanisms */
441 : /* are used to accelerate this when possible. */
442 : /************************************************************************/
443 :
444 0 : int CPCIDSKVectorSegment::IndexFromShapeId( ShapeId id )
445 :
446 : {
447 0 : if( id == NullShapeId )
448 0 : return -1;
449 :
450 0 : Initialize();
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* Does this match our last lookup? */
454 : /* -------------------------------------------------------------------- */
455 0 : if( id == last_shapes_id )
456 0 : return last_shapes_index;
457 :
458 : /* -------------------------------------------------------------------- */
459 : /* Is this the next shapeid in sequence, and is it in our */
460 : /* loaded index cache? */
461 : /* -------------------------------------------------------------------- */
462 0 : if( id == last_shapes_id + 1
463 : && last_shapes_index + 1 >= shape_index_start
464 : && last_shapes_index + 1 < shape_index_start + (int) shape_index_ids.size() )
465 : {
466 0 : last_shapes_index++;
467 0 : last_shapes_id++;
468 0 : return last_shapes_index;
469 : }
470 :
471 : /* -------------------------------------------------------------------- */
472 : /* Activate the shapeid map, if it is not already active. */
473 : /* -------------------------------------------------------------------- */
474 0 : shapeid_map_active = true;
475 :
476 : /* -------------------------------------------------------------------- */
477 : /* Is this already in our shapeid map? */
478 : /* -------------------------------------------------------------------- */
479 0 : if( shapeid_map.count( id ) == 1 )
480 0 : return shapeid_map[id];
481 :
482 : /* -------------------------------------------------------------------- */
483 : /* Load shapeid index pages until we find the desired shapeid, */
484 : /* or we run out. */
485 : /* -------------------------------------------------------------------- */
486 0 : int shapeid_pages = (shape_count+shapeid_page_size-1) / shapeid_page_size;
487 :
488 0 : while( shapeid_pages_certainly_mapped+1 < shapeid_pages )
489 : {
490 : AccessShapeByIndex(
491 0 : (shapeid_pages_certainly_mapped+1) * shapeid_page_size );
492 :
493 0 : if( shapeid_map.count( id ) == 1 )
494 0 : return shapeid_map[id];
495 : }
496 :
497 0 : return -1;
498 : }
499 :
500 : /************************************************************************/
501 : /* AccessShapeByIndex() */
502 : /* */
503 : /* This method is responsible for loading the set of */
504 : /* information for shape "shape_index" into the shape_index data */
505 : /* structures if it is not already there. */
506 : /************************************************************************/
507 :
508 0 : void CPCIDSKVectorSegment::AccessShapeByIndex( int shape_index )
509 :
510 : {
511 0 : Initialize();
512 :
513 : /* -------------------------------------------------------------------- */
514 : /* Is the requested index already loaded? */
515 : /* -------------------------------------------------------------------- */
516 0 : if( shape_index >= shape_index_start
517 : && shape_index < shape_index_start + (int) shape_index_ids.size() )
518 0 : return;
519 :
520 : /* -------------------------------------------------------------------- */
521 : /* Load a chunk of shape index information into a */
522 : /* PCIDSKBuffer. */
523 : /* -------------------------------------------------------------------- */
524 0 : int entries_to_load = shapeid_page_size;
525 :
526 0 : shape_index_start = shape_index - (shape_index % shapeid_page_size);
527 0 : if( shape_index_start + entries_to_load > shape_count )
528 0 : entries_to_load = shape_count - shape_index_start;
529 :
530 0 : PCIDSKBuffer wrk_index;
531 0 : wrk_index.SetSize( entries_to_load * 12 );
532 :
533 : ReadFromFile( wrk_index.buffer,
534 : shape_index_byte_offset + shape_index_start*12,
535 0 : wrk_index.buffer_size );
536 :
537 : /* -------------------------------------------------------------------- */
538 : /* Parse into the vectors for easier use. */
539 : /* -------------------------------------------------------------------- */
540 : int i;
541 :
542 0 : shape_index_ids.resize( entries_to_load );
543 0 : shape_index_vertex_off.resize( entries_to_load );
544 0 : shape_index_record_off.resize( entries_to_load );
545 :
546 0 : for( i = 0; i < entries_to_load; i++ )
547 : {
548 0 : memcpy( &(shape_index_ids[i]), wrk_index.buffer + i*12, 4 );
549 0 : memcpy( &(shape_index_vertex_off[i]), wrk_index.buffer + i*12+4, 4 );
550 0 : memcpy( &(shape_index_record_off[i]), wrk_index.buffer + i*12+8, 4 );
551 : }
552 :
553 0 : if( needs_swap )
554 : {
555 0 : SwapData( &(shape_index_ids[0]), 4, entries_to_load );
556 0 : SwapData( &(shape_index_vertex_off[0]), 4, entries_to_load );
557 0 : SwapData( &(shape_index_record_off[0]), 4, entries_to_load );
558 : }
559 :
560 : /* -------------------------------------------------------------------- */
561 : /* If the shapeid map is active, apply the current pages */
562 : /* shapeids if it does not already appear to have been */
563 : /* applied. */
564 : /* -------------------------------------------------------------------- */
565 0 : int loaded_page = shape_index_start / shapeid_page_size;
566 :
567 0 : if( shapeid_map_active
568 : && shape_index_ids.size() > 0
569 : && shapeid_map.count( shape_index_ids[0] ) == 0 )
570 : {
571 0 : for( i = 0; i < entries_to_load; i++ )
572 : {
573 0 : if( shape_index_ids[i] != NullShapeId )
574 0 : shapeid_map[shape_index_ids[i]] = i+shape_index_start;
575 : }
576 :
577 0 : if( loaded_page == shapeid_pages_certainly_mapped+1 )
578 0 : shapeid_pages_certainly_mapped++;
579 0 : }
580 : }
581 :
582 : /************************************************************************/
583 : /* FindFirst() */
584 : /************************************************************************/
585 :
586 0 : ShapeId CPCIDSKVectorSegment::FindFirst()
587 : {
588 0 : Initialize();
589 :
590 0 : if( shape_count == 0 )
591 0 : return NullShapeId;
592 :
593 0 : AccessShapeByIndex( 0 );
594 :
595 0 : last_shapes_id = shape_index_ids[0];
596 0 : last_shapes_index = 0;
597 :
598 0 : return last_shapes_id;
599 : }
600 :
601 : /************************************************************************/
602 : /* FindNext() */
603 : /************************************************************************/
604 :
605 0 : ShapeId CPCIDSKVectorSegment::FindNext( ShapeId previous_id )
606 : {
607 0 : if( previous_id == NullShapeId )
608 0 : return FindFirst();
609 :
610 0 : int previous_index = IndexFromShapeId( previous_id );
611 :
612 0 : if( previous_index == shape_count - 1 )
613 0 : return NullShapeId;
614 :
615 0 : AccessShapeByIndex( previous_index+1 );
616 :
617 0 : last_shapes_index = previous_index+1;
618 0 : last_shapes_id = shape_index_ids[last_shapes_index - shape_index_start];
619 :
620 0 : return last_shapes_id;
621 : }
622 :
623 : /************************************************************************/
624 : /* GetVertices() */
625 : /************************************************************************/
626 :
627 0 : void CPCIDSKVectorSegment::GetVertices( ShapeId shape_id,
628 : std::vector<ShapeVertex> &vertices )
629 :
630 : {
631 0 : int shape_index = IndexFromShapeId( shape_id );
632 :
633 0 : AccessShapeByIndex( shape_index );
634 :
635 0 : uint32 vert_off = shape_index_vertex_off[shape_index - shape_index_start];
636 : uint32 vertex_count;
637 :
638 0 : memcpy( &vertex_count, GetData( sec_vert, vert_off+4, NULL, 4 ), 4 );
639 0 : if( needs_swap )
640 0 : SwapData( &vertex_count, 4, 1 );
641 :
642 0 : vertices.resize( vertex_count );
643 :
644 : // We ought to change this to process the available data and
645 : // then request more.
646 : memcpy( &(vertices[0]),
647 : GetData( sec_vert, vert_off+8, NULL, vertex_count*24),
648 0 : vertex_count * 24 );
649 0 : if( needs_swap )
650 0 : SwapData( &(vertices[0]), 8, vertex_count*3 );
651 0 : }
652 :
653 : /************************************************************************/
654 : /* GetFieldCount() */
655 : /************************************************************************/
656 :
657 0 : int CPCIDSKVectorSegment::GetFieldCount()
658 :
659 : {
660 0 : Initialize();
661 :
662 0 : return field_names.size();
663 : }
664 :
665 : /************************************************************************/
666 : /* GetFieldName() */
667 : /************************************************************************/
668 :
669 0 : std::string CPCIDSKVectorSegment::GetFieldName( int field_index )
670 :
671 : {
672 0 : Initialize();
673 :
674 0 : return field_names[field_index];
675 : }
676 :
677 : /************************************************************************/
678 : /* GetFieldDescription() */
679 : /************************************************************************/
680 :
681 0 : std::string CPCIDSKVectorSegment::GetFieldDescription( int field_index )
682 :
683 : {
684 0 : Initialize();
685 :
686 0 : return field_descriptions[field_index];
687 : }
688 :
689 : /************************************************************************/
690 : /* GetFieldType() */
691 : /************************************************************************/
692 :
693 0 : ShapeFieldType CPCIDSKVectorSegment::GetFieldType( int field_index )
694 :
695 : {
696 0 : Initialize();
697 :
698 0 : return field_types[field_index];
699 : }
700 :
701 : /************************************************************************/
702 : /* GetFieldFormat() */
703 : /************************************************************************/
704 :
705 0 : std::string CPCIDSKVectorSegment::GetFieldFormat( int field_index )
706 :
707 : {
708 0 : Initialize();
709 :
710 0 : return field_formats[field_index];
711 : }
712 :
713 : /************************************************************************/
714 : /* GetFieldDefault() */
715 : /************************************************************************/
716 :
717 0 : ShapeField CPCIDSKVectorSegment::GetFieldDefault( int field_index )
718 :
719 : {
720 0 : Initialize();
721 :
722 0 : return field_defaults[field_index];
723 : }
724 :
725 : /************************************************************************/
726 : /* GetFields() */
727 : /************************************************************************/
728 :
729 0 : void CPCIDSKVectorSegment::GetFields( ShapeId id,
730 : std::vector<ShapeField>& list )
731 :
732 : {
733 : unsigned int i;
734 0 : int shape_index = IndexFromShapeId( id );
735 :
736 0 : AccessShapeByIndex( shape_index );
737 :
738 0 : uint32 offset = shape_index_record_off[shape_index - shape_index_start] + 4;
739 :
740 0 : list.resize(field_names.size());
741 0 : for( i = 0; i < field_names.size(); i++ )
742 0 : offset = ReadField( offset, list[i], field_types[i], sec_record );
743 0 : }
|