public bool check_item(LASitem item) { switch(item.type) { case LASitem.Type.POINT10: if(item.size!=20) return return_error("POINT10 has size != 20"); if(item.version>2) return return_error("POINT10 has version > 2"); break; case LASitem.Type.GPSTIME11: if(item.size!=8) return return_error("GPSTIME11 has size != 8"); if(item.version>2) return return_error("GPSTIME11 has version > 2"); break; case LASitem.Type.RGB12: if(item.size!=6) return return_error("RGB12 has size != 6"); if(item.version>2) return return_error("RGB12 has version > 2"); break; case LASitem.Type.WAVEPACKET13: if(item.size!=29) return return_error("WAVEPACKET13 has size != 29"); if(item.version>1) return return_error("WAVEPACKET13 has version > 1"); break; case LASitem.Type.BYTE: if(item.size<1) return return_error("BYTE has size < 1"); if(item.version>2) return return_error("BYTE has version > 2"); break; case LASitem.Type.POINT14: if(item.size!=30) return return_error("POINT14 has size != 30"); if(item.version>0) return return_error("POINT14 has version > 0"); break; case LASitem.Type.RGBNIR14: if(item.size!=8) return return_error("RGBNIR14 has size != 8"); if(item.version>0) return return_error("RGBNIR14 has version > 0"); break; default: if(true) return return_error(string.Format("item unknown ({0},{1},{2})", item.type, item.size, item.version)); } return true; }
// should only be called *once* public bool setup(uint num_items, LASitem[] items, LASzip laszip=null) { // is laszip exists then we must use its items if(laszip!=null) { if(num_items!=laszip.num_items) return false; if(items!=laszip.items) return false; } // create entropy encoder (if requested) enc=null; if(laszip!=null&&laszip.compressor!=0) { switch(laszip.coder) { case LASzip.CODER_ARITHMETIC: enc=new ArithmeticEncoder(); break; default: return false; // entropy decoder not supported } } // initizalize the writers writers=null; num_writers=num_items; // disable chunking chunk_size=uint.MaxValue; // always create the raw writers writers_raw=new LASwriteItem[num_writers]; for(uint i=0; i<num_writers; i++) { switch(items[i].type) { case LASitem.Type.POINT10: writers_raw[i]=new LASwriteItemRaw_POINT10(); break; case LASitem.Type.GPSTIME11: writers_raw[i]=new LASwriteItemRaw_GPSTIME11(); break; case LASitem.Type.RGB12: writers_raw[i]=new LASwriteItemRaw_RGB12(); break; case LASitem.Type.WAVEPACKET13: writers_raw[i]=new LASwriteItemRaw_WAVEPACKET13(); break; case LASitem.Type.BYTE: writers_raw[i]=new LASwriteItemRaw_BYTE(items[i].size); break; case LASitem.Type.POINT14: writers_raw[i]=new LASwriteItemRaw_POINT14(); break; case LASitem.Type.RGBNIR14: writers_raw[i]=new LASwriteItemRaw_RGBNIR14(); break; default: return false; } } // if needed create the compressed writers and set versions if(enc!=null) { writers_compressed=new LASwriteItem[num_writers]; for(uint i=0; i<num_writers; i++) { switch(items[i].type) { case LASitem.Type.POINT10: if(items[i].version==1) throw new NotSupportedException("Version 1 POINT10 is no longer supported, use version 2."); else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_POINT10_v2(enc); else return false; break; case LASitem.Type.GPSTIME11: if(items[i].version==1) throw new NotSupportedException("Version 1 GPSTIME11 is no longer supported, use version 2."); else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_GPSTIME11_v2(enc); else return false; break; case LASitem.Type.RGB12: if(items[i].version==1) throw new NotSupportedException("Version 1 RGB12 is no longer supported, use version 2."); else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_RGB12_v2(enc); else return false; break; case LASitem.Type.WAVEPACKET13: if(items[i].version==1) writers_compressed[i]=new LASwriteItemCompressed_WAVEPACKET13_v1(enc); else return false; break; case LASitem.Type.BYTE: if(items[i].version==1) throw new NotSupportedException("Version 1 BYTE is no longer supported, use version 2."); else if(items[i].version==2) writers_compressed[i]=new LASwriteItemCompressed_BYTE_v2(enc, items[i].size); else return false; break; default: return false; } } if(laszip.compressor==LASzip.COMPRESSOR_POINTWISE_CHUNKED) { if(laszip.chunk_size!=0) chunk_size=laszip.chunk_size; chunk_count=0; init_chunking=true; } } return true; }
public unsafe bool unpack(byte[] bytes, int num) { // check input if(num<34) return return_error("too few bytes to unpack"); if(((num-34)%6)!=0) return return_error("wrong number bytes to unpack"); if(((num-34)/6)==0) return return_error("zero items to unpack"); num_items=(ushort)((num-34)/6); // create item list items=new LASitem[num_items]; // do the unpacking ushort i; fixed(byte* pBytes=bytes) { byte* b=pBytes; compressor=*((ushort*)b); b+=2; coder=*((ushort*)b); b+=2; version_major=*b; b+=1; version_minor=*b; b+=1; version_revision=*((ushort*)b); b+=2; options=*((uint*)b); b+=4; chunk_size=*((uint*)b); b+=4; number_of_special_evlrs=*((long*)b); b+=8; offset_to_special_evlrs=*((long*)b); b+=8; num_items=*((ushort*)b); b+=2; for(i=0; i<num_items; i++) { items[i].type=(LASitem.Type)(int)*((ushort*)b); b+=2; items[i].size=*((ushort*)b); b+=2; items[i].version=*((ushort*)b); b+=2; } Debug.Assert((pBytes+num)==b); // check if we support the contents for(i=0; i<num_items; i++) { if(!check_item(items[i])) return false; } return true; } }
public bool setup(ushort num_items, LASitem[] items, ushort compressor) { // check input if(!check_compressor(compressor)) return false; if(!check_items(num_items, items)) return false; // setup compressor this.compressor=compressor; if(this.compressor==COMPRESSOR_POINTWISE_CHUNKED) { if(chunk_size==0) chunk_size=CHUNK_SIZE_DEFAULT; } // prepare items this.num_items=0; this.items=null; this.num_items=num_items; this.items=new LASitem[num_items]; // setup items for(int i=0; i<num_items; i++) { this.items[i]=items[i]; } return true; }
// go back and forth between item array and point type & size public bool setup(out ushort num_items, out LASitem[] items, byte point_type, ushort point_size, ushort compressor=COMPRESSOR_NONE) { num_items=0; items=null; bool have_point14=false; bool have_gps_time=false; bool have_rgb=false; bool have_nir=false; bool have_wavepacket=false; int extra_bytes_number=0; // switch over the point types we know switch(point_type) { case 0: extra_bytes_number=(int)point_size-20; break; case 1: have_gps_time=true; extra_bytes_number=(int)point_size-28; break; case 2: have_rgb=true; extra_bytes_number=(int)point_size-26; break; case 3: have_gps_time=true; have_rgb=true; extra_bytes_number=(int)point_size-34; break; case 4: have_gps_time=true; have_wavepacket=true; extra_bytes_number=(int)point_size-57; break; case 5: have_gps_time=true; have_rgb=true; have_wavepacket=true; extra_bytes_number=(int)point_size-63; break; case 6: have_point14=true; extra_bytes_number=(int)point_size-30; break; case 7: have_point14=true; have_rgb=true; extra_bytes_number=(int)point_size-36; break; case 8: have_point14=true; have_rgb=true; have_nir=true; extra_bytes_number=(int)point_size-38; break; case 9: have_point14=true; have_wavepacket=true; extra_bytes_number=(int)point_size-59; break; case 10: have_point14=true; have_rgb=true; have_nir=true; have_wavepacket=true; extra_bytes_number=(int)point_size-67; break; default: if(true) return return_error(string.Format("point type {0} unknown", point_type)); } if(extra_bytes_number<0) { Console.Error.WriteLine("WARNING: point size {0} too small by {1} bytes for point type {2}. assuming point_size of {3}", point_size, -extra_bytes_number, point_type, point_size-extra_bytes_number); extra_bytes_number=0; } // create item description num_items=(ushort)(1+(have_gps_time?1:0)+(have_rgb?1:0)+(have_wavepacket?1:0)+(extra_bytes_number!=0?1:0)); items=new LASitem[num_items]; ushort i=1; if(have_point14) { items[0]=new LASitem(); items[0].type=LASitem.Type.POINT14; items[0].size=30; items[0].version=0; } else { items[0]=new LASitem(); items[0].type=LASitem.Type.POINT10; items[0].size=20; items[0].version=0; } if(have_gps_time) { items[i]=new LASitem(); items[i].type=LASitem.Type.GPSTIME11; items[i].size=8; items[i].version=0; i++; } if(have_rgb) { items[i]=new LASitem(); if(have_nir) { items[i].type=LASitem.Type.RGBNIR14; items[i].size=8; items[i].version=0; } else { items[i].type=LASitem.Type.RGB12; items[i].size=6; items[i].version=0; } i++; } if(have_wavepacket) { items[i]=new LASitem(); items[i].type=LASitem.Type.WAVEPACKET13; items[i].size=29; items[i].version=0; i++; } if(extra_bytes_number!=0) { items[i]=new LASitem(); items[i].type=LASitem.Type.BYTE; items[i].size=(ushort)extra_bytes_number; items[i].version=0; i++; } if(compressor!=0) request_version(2); Debug.Assert(i==num_items); return true; }
public bool is_standard(ushort num_items, LASitem[] items, out byte point_type, out ushort record_length) { // this is always true point_type=127; record_length=0; if(items==null) return return_error("LASitem array is zero"); for(int i=0; i<num_items; i++) record_length+=items[i].size; // the minimal number of items is 1 if(num_items<1) return return_error("less than one LASitem entries"); // the maximal number of items is 5 if(num_items>5) return return_error("more than five LASitem entries"); if(items[0].is_type(LASitem.Type.POINT10)) { // consider all the POINT10 combinations if(num_items==1) { point_type=0; Debug.Assert(record_length==20); return true; } else { if(items[1].is_type(LASitem.Type.GPSTIME11)) { if(num_items==2) { point_type=1; Debug.Assert(record_length==28); return true; } else { if(items[2].is_type(LASitem.Type.RGB12)) { if(num_items==3) { point_type=3; Debug.Assert(record_length==34); return true; } else { if(items[3].is_type(LASitem.Type.WAVEPACKET13)) { if(num_items==4) { point_type=5; Debug.Assert(record_length==63); return true; } else { if(items[4].is_type(LASitem.Type.BYTE)) { if(num_items==5) { point_type=5; Debug.Assert(record_length==(63+items[4].size)); return true; } } } } else if(items[3].is_type(LASitem.Type.BYTE)) { if(num_items==4) { point_type=3; Debug.Assert(record_length==(34+items[3].size)); return true; } } } } else if(items[2].is_type(LASitem.Type.WAVEPACKET13)) { if(num_items==3) { point_type=4; Debug.Assert(record_length==57); return true; } else { if(items[3].is_type(LASitem.Type.BYTE)) { if(num_items==4) { point_type=4; Debug.Assert(record_length==(57+items[3].size)); return true; } } } } else if(items[2].is_type(LASitem.Type.BYTE)) { if(num_items==3) { point_type=1; Debug.Assert(record_length==(28+items[2].size)); return true; } } } } else if(items[1].is_type(LASitem.Type.RGB12)) { if(num_items==2) { point_type=2; Debug.Assert(record_length==26); return true; } else { if(items[2].is_type(LASitem.Type.BYTE)) { if(num_items==3) { point_type=2; Debug.Assert(record_length==(26+items[2].size)); return true; } } } } else if(items[1].is_type(LASitem.Type.BYTE)) { if(num_items==2) { point_type=0; Debug.Assert(record_length==(20+items[1].size)); return true; } } } } else if(items[0].is_type(LASitem.Type.POINT14)) { // consider all the POINT14 combinations if(num_items==1) { point_type=6; Debug.Assert(record_length==30); return true; } else { if(items[1].is_type(LASitem.Type.RGB12)) { if(num_items==2) { point_type=7; Debug.Assert(record_length==36); return true; } else { if(items[2].is_type(LASitem.Type.BYTE)) { if(num_items==3) { point_type=7; Debug.Assert(record_length==(36+items[2].size)); return true; } } } } else if(items[1].is_type(LASitem.Type.RGBNIR14)) { if(num_items==2) { point_type=8; Debug.Assert(record_length==38); return true; } else { if(items[2].is_type(LASitem.Type.WAVEPACKET13)) { if(num_items==3) { point_type=10; Debug.Assert(record_length==67); return true; } else { if(items[3].is_type(LASitem.Type.BYTE)) { if(num_items==4) { point_type=10; Debug.Assert(record_length==(67+items[3].size)); return true; } } } } else if(items[2].is_type(LASitem.Type.BYTE)) { if(num_items==3) { point_type=8; Debug.Assert(record_length==(38+items[2].size)); return true; } } } } else if(items[1].is_type(LASitem.Type.WAVEPACKET13)) { if(num_items==2) { point_type=9; Debug.Assert(record_length==59); return true; } else { if(items[2].is_type(LASitem.Type.BYTE)) { if(num_items==3) { point_type=9; Debug.Assert(record_length==(59+items[2].size)); return true; } } } } else if(items[1].is_type(LASitem.Type.BYTE)) { if(num_items==2) { point_type=6; Debug.Assert(record_length==(30+items[1].size)); return true; } } } } else { return_error("first LASitem is neither POINT10 nor POINT14"); } return return_error("LASitem array does not match LAS specification 1.4"); }
public bool check_items(ushort num_items, LASitem[] items) { if(num_items==0) return return_error("number of items cannot be zero"); if(items==null) return return_error("items pointer cannot be NULL"); for(int i=0; i<num_items; i++) { if(!check_item(items[i])) return false; } return true; }
// should only be called *once* public bool setup(uint num_items, LASitem[] items, LASzip laszip=null) { // is laszip exists then we must use its items if(laszip!=null) { if(num_items!=laszip.num_items) return false; if(items!=laszip.items) return false; } // create entropy decoder (if requested) dec=null; if(laszip!=null&&laszip.compressor!=0) { switch(laszip.coder) { case LASzip.CODER_ARITHMETIC: dec=new ArithmeticDecoder(); break; default: return false; // entropy decoder not supported } } // initizalize the readers readers=null; num_readers=num_items; // disable chunking chunk_size=uint.MaxValue; // always create the raw readers readers_raw=new LASreadItem[num_readers]; for(int i=0; i<num_readers; i++) { switch(items[i].type) { case LASitem.Type.POINT10: readers_raw[i]=new LASreadItemRaw_POINT10(); break; case LASitem.Type.GPSTIME11: readers_raw[i]=new LASreadItemRaw_GPSTIME11(); break; case LASitem.Type.RGB12: readers_raw[i]=new LASreadItemRaw_RGB12(); break; case LASitem.Type.WAVEPACKET13: readers_raw[i]=new LASreadItemRaw_WAVEPACKET13(); break; case LASitem.Type.BYTE: readers_raw[i]=new LASreadItemRaw_BYTE(items[i].size); break; case LASitem.Type.POINT14: readers_raw[i]=new LASreadItemRaw_POINT14(); break; case LASitem.Type.RGBNIR14: readers_raw[i]=new LASreadItemRaw_RGBNIR14(); break; default: return false; } point_size+=items[i].size; } if(dec!=null) { readers_compressed=new LASreadItem[num_readers]; // seeks with compressed data need a seek point for(int i=0; i<num_readers; i++) { switch(items[i].type) { case LASitem.Type.POINT10: if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_POINT10_v1(dec); else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_POINT10_v2(dec); else return false; break; case LASitem.Type.GPSTIME11: if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_GPSTIME11_v1(dec); else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_GPSTIME11_v2(dec); else return false; break; case LASitem.Type.RGB12: if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_RGB12_v1(dec); else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_RGB12_v2(dec); else return false; break; case LASitem.Type.WAVEPACKET13: if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_WAVEPACKET13_v1(dec); else return false; break; case LASitem.Type.BYTE: seek_point.extra_bytes=new byte[items[i].size]; seek_point.num_extra_bytes=items[i].size; if(items[i].version==1) readers_compressed[i]=new LASreadItemCompressed_BYTE_v1(dec, items[i].size); else if(items[i].version==2) readers_compressed[i]=new LASreadItemCompressed_BYTE_v2(dec, items[i].size); else return false; break; default: return false; } } if(laszip.compressor==LASzip.COMPRESSOR_POINTWISE_CHUNKED) { if(laszip.chunk_size!=0) chunk_size=laszip.chunk_size; number_chunks=uint.MaxValue; } } return true; }
public bool check_item(LASitem item) { switch (item.type) { case LASitem.Type.POINT10: if (item.size != 20) { return(return_error("POINT10 has size != 20")); } if (item.version > 2) { return(return_error("POINT10 has version > 2")); } break; case LASitem.Type.GPSTIME11: if (item.size != 8) { return(return_error("GPSTIME11 has size != 8")); } if (item.version > 2) { return(return_error("GPSTIME11 has version > 2")); } break; case LASitem.Type.RGB12: if (item.size != 6) { return(return_error("RGB12 has size != 6")); } if (item.version > 2) { return(return_error("RGB12 has version > 2")); } break; case LASitem.Type.WAVEPACKET13: if (item.size != 29) { return(return_error("WAVEPACKET13 has size != 29")); } if (item.version > 1) { return(return_error("WAVEPACKET13 has version > 1")); } break; case LASitem.Type.BYTE: if (item.size < 1) { return(return_error("BYTE has size < 1")); } if (item.version > 2) { return(return_error("BYTE has version > 2")); } break; case LASitem.Type.POINT14: if (item.size != 30) { return(return_error("POINT14 has size != 30")); } if (item.version > 0) { return(return_error("POINT14 has version > 0")); } break; case LASitem.Type.RGBNIR14: if (item.size != 8) { return(return_error("RGBNIR14 has size != 8")); } if (item.version > 0) { return(return_error("RGBNIR14 has version > 0")); } break; default: if (true) { return(return_error(string.Format("item unknown ({0},{1},{2})", item.type, item.size, item.version))); } } return(true); }
public unsafe bool unpack(byte[] bytes, int num) { // check input if (num < 34) { return(return_error("too few bytes to unpack")); } if (((num - 34) % 6) != 0) { return(return_error("wrong number bytes to unpack")); } if (((num - 34) / 6) == 0) { return(return_error("zero items to unpack")); } num_items = (ushort)((num - 34) / 6); // create item list items = new LASitem[num_items]; // do the unpacking ushort i; fixed(byte *pBytes = bytes) { byte *b = pBytes; compressor = *((ushort *)b); b += 2; coder = *((ushort *)b); b += 2; version_major = *b; b += 1; version_minor = *b; b += 1; version_revision = *((ushort *)b); b += 2; options = *((uint *)b); b += 4; chunk_size = *((uint *)b); b += 4; number_of_special_evlrs = *((long *)b); b += 8; offset_to_special_evlrs = *((long *)b); b += 8; num_items = *((ushort *)b); b += 2; for (i = 0; i < num_items; i++) { items[i].type = (LASitem.Type)(int) * ((ushort *)b); b += 2; items[i].size = *((ushort *)b); b += 2; items[i].version = *((ushort *)b); b += 2; } Debug.Assert((pBytes + num) == b); // check if we support the contents for (i = 0; i < num_items; i++) { if (!check_item(items[i])) { return(false); } } return(true); } }
// go back and forth between item array and point type & size public bool setup(out ushort num_items, out LASitem[] items, byte point_type, ushort point_size, ushort compressor = COMPRESSOR_NONE) { num_items = 0; items = null; bool have_point14 = false; bool have_gps_time = false; bool have_rgb = false; bool have_nir = false; bool have_wavepacket = false; int extra_bytes_number = 0; // switch over the point types we know switch (point_type) { case 0: extra_bytes_number = (int)point_size - 20; break; case 1: have_gps_time = true; extra_bytes_number = (int)point_size - 28; break; case 2: have_rgb = true; extra_bytes_number = (int)point_size - 26; break; case 3: have_gps_time = true; have_rgb = true; extra_bytes_number = (int)point_size - 34; break; case 4: have_gps_time = true; have_wavepacket = true; extra_bytes_number = (int)point_size - 57; break; case 5: have_gps_time = true; have_rgb = true; have_wavepacket = true; extra_bytes_number = (int)point_size - 63; break; case 6: have_point14 = true; extra_bytes_number = (int)point_size - 30; break; case 7: have_point14 = true; have_rgb = true; extra_bytes_number = (int)point_size - 36; break; case 8: have_point14 = true; have_rgb = true; have_nir = true; extra_bytes_number = (int)point_size - 38; break; case 9: have_point14 = true; have_wavepacket = true; extra_bytes_number = (int)point_size - 59; break; case 10: have_point14 = true; have_rgb = true; have_nir = true; have_wavepacket = true; extra_bytes_number = (int)point_size - 67; break; default: if (true) { return(return_error(string.Format("point type {0} unknown", point_type))); } } if (extra_bytes_number < 0) { Console.Error.WriteLine("WARNING: point size {0} too small by {1} bytes for point type {2}. assuming point_size of {3}", point_size, -extra_bytes_number, point_type, point_size - extra_bytes_number); extra_bytes_number = 0; } // create item description num_items = (ushort)(1 + (have_gps_time?1:0) + (have_rgb?1:0) + (have_wavepacket?1:0) + (extra_bytes_number != 0?1:0)); items = new LASitem[num_items]; ushort i = 1; if (have_point14) { items[0] = new LASitem(); items[0].type = LASitem.Type.POINT14; items[0].size = 30; items[0].version = 0; } else { items[0] = new LASitem(); items[0].type = LASitem.Type.POINT10; items[0].size = 20; items[0].version = 0; } if (have_gps_time) { items[i] = new LASitem(); items[i].type = LASitem.Type.GPSTIME11; items[i].size = 8; items[i].version = 0; i++; } if (have_rgb) { items[i] = new LASitem(); if (have_nir) { items[i].type = LASitem.Type.RGBNIR14; items[i].size = 8; items[i].version = 0; } else { items[i].type = LASitem.Type.RGB12; items[i].size = 6; items[i].version = 0; } i++; } if (have_wavepacket) { items[i] = new LASitem(); items[i].type = LASitem.Type.WAVEPACKET13; items[i].size = 29; items[i].version = 0; i++; } if (extra_bytes_number != 0) { items[i] = new LASitem(); items[i].type = LASitem.Type.BYTE; items[i].size = (ushort)extra_bytes_number; items[i].version = 0; i++; } if (compressor != 0) { request_version(2); } Debug.Assert(i == num_items); return(true); }