SAGA API Version 9.13
Loading...
Searching...
No Matches
pointcloud.cpp
Go to the documentation of this file.
1
3// //
4// SAGA //
5// //
6// System for Automated Geoscientific Analyses //
7// //
8// Application Programming Interface //
9// //
10// Library: SAGA_API //
11// //
12//-------------------------------------------------------//
13// //
14// pointcloud.cpp //
15// //
16// Copyright (C) 2009 by Olaf Conrad //
17// //
18//-------------------------------------------------------//
19// //
20// This file is part of 'SAGA - System for Automated //
21// Geoscientific Analyses'. //
22// //
23// This library is free software; you can redistribute //
24// it and/or modify it under the terms of the GNU Lesser //
25// General Public License as published by the Free //
26// Software Foundation, either version 2.1 of the //
27// License, or (at your option) any later version. //
28// //
29// This library is distributed in the hope that it will //
30// be useful, but WITHOUT ANY WARRANTY; without even the //
31// implied warranty of MERCHANTABILITY or FITNESS FOR A //
32// PARTICULAR PURPOSE. See the GNU Lesser General Public //
33// License for more details. //
34// //
35// You should have received a copy of the GNU Lesser //
36// General Public License along with this program; if //
37// not, see <http://www.gnu.org/licenses/>. //
38// //
39//-------------------------------------------------------//
40// //
41// contact: Olaf Conrad //
42// Institute of Geography //
43// University of Hamburg //
44// Germany //
45// //
46// e-mail: oconrad@saga-gis.org //
47// //
49
50//---------------------------------------------------------
51#include "pointcloud.h"
52
53
55// //
56// //
57// //
59
60//---------------------------------------------------------
61#define PC_FILE_VERSION "SGPC01"
62
63#define PC_SIZE_STRING 32
64#define PC_SIZE_DATE 32
65#define PC_SIZE_TYPE(type) (type == SG_DATATYPE_String ? PC_SIZE_STRING : type == SG_DATATYPE_Date ? PC_SIZE_DATE : (int)SG_Data_Type_Get_Size(type))
66#define PC_SIZE_FIELD(field) PC_SIZE_TYPE(m_Field_Info[field]->m_Type)
67
68
70// //
71// //
72// //
74
75//---------------------------------------------------------
77{
78 return( new CSG_PointCloud );
79}
80
81//---------------------------------------------------------
83{
84 return( new CSG_PointCloud(PointCloud) );
85}
86
87//---------------------------------------------------------
88CSG_PointCloud * SG_Create_PointCloud(const char *File) { return( SG_Create_PointCloud(CSG_String(File)) ); }
89CSG_PointCloud * SG_Create_PointCloud(const wchar_t *File) { return( SG_Create_PointCloud(CSG_String(File)) ); }
91{
92 CSG_PointCloud *pPoints = new CSG_PointCloud();
93
94 if( pPoints->Create(File) )
95 {
96 return( pPoints );
97 }
98
99 delete(pPoints); return( NULL );
100}
101
102//---------------------------------------------------------
104{
105 return( new CSG_PointCloud(pStructure) );
106}
107
108
110// //
111// //
112// //
114
115//---------------------------------------------------------
121
123{
124 Destroy();
125
126 Add_Field("", SG_DATATYPE_Undefined); // add x, y, z fields
127
128 return( true );
129}
130
131//---------------------------------------------------------
133 : CSG_Shapes()
134{
135 _On_Construction(); Create(PointCloud);
136}
137
139{
140 return( Assign((CSG_Data_Object *)&PointCloud) );
141}
142
143//---------------------------------------------------------
151
152bool CSG_PointCloud::Create(const char *File) { return( Create(CSG_String(File)) ); }
153bool CSG_PointCloud::Create(const wchar_t *File) { return( Create(CSG_String(File)) ); }
155{
156 return( _Load(File) );
157}
158
159//---------------------------------------------------------
161 : CSG_Shapes()
162{
163 _On_Construction(); Create(pTemplate);
164}
165
167{
168 Destroy();
169
170 if( pTemplate && pTemplate->m_nFields > 0 )
171 {
172 for(int i=0; i<pTemplate->m_nFields; i++)
173 {
174 _Add_Field(pTemplate->m_Field_Info[i]->m_Name, pTemplate->m_Field_Info[i]->m_Type);
175 }
176
177 return( true );
178 }
179
180 return( false );
181}
182
183//---------------------------------------------------------
185{
188
189 Set_NoData_Value(-999999);
190
192
193 m_Shapes.Create(SHAPE_TYPE_Point, NULL, NULL, SG_VERTEX_TYPE_XYZ);
194 m_Shapes.Set_Count(SG_OMP_Get_Max_Num_Procs());
195 for(sLong i=0; i<m_Shapes.Get_Count(); i++)
196 {
197 m_Shapes[i].m_Index = -1;
198 }
199
200 m_Array_Points.Create(sizeof(char *), 0, TSG_Array_Growth::SG_ARRAY_GROWTH_3);
201}
202
203//---------------------------------------------------------
208
210{
211 Del_Points();
212
213 if( m_nFields > 0 )
214 {
215 for(int i=0; i<m_nFields; i++)
216 {
217 delete(m_Field_Info[i]);
218 }
219
221 SG_Free(m_Field_Offset); m_Field_Offset = NULL;
222
223 m_nFields = 0;
224
226 }
227
229
230 return( true );
231}
232
233
235// //
236// File //
237// //
239
240//---------------------------------------------------------
241bool CSG_PointCloud::_Load(const CSG_String &File)
242{
243 SG_UI_Msg_Add(CSG_String::Format("%s %s: %s...", _TL("Loading"), _TL("point cloud"), File.c_str()), true);
244
245 bool bResult = false;
246
247 if( SG_File_Cmp_Extension(File, "sg-pts-z") ) // POINTCLOUD_FILE_FORMAT_Compressed
248 {
249 CSG_Archive Stream(File, SG_FILE_R);
250
251 CSG_String _File(SG_File_Get_Name(File, false) + ".");
252
253 if( (bResult = Stream.Get_File(_File + "sg-pts")) == false )
254 {
255 for(size_t i=0; i<Stream.Get_File_Count(); i++)
256 {
257 if( SG_File_Cmp_Extension(Stream.Get_File_Name(i), "sg-pts") )
258 {
259 _File = SG_File_Get_Name(Stream.Get_File_Name(i), false) + ".";
260
261 break;
262 }
263 }
264
265 bResult = Stream.Get_File(_File + "sg-pts");
266 }
267
268 if( bResult && _Load(Stream) )
269 {
270 if( Stream.Get_File(_File + "sg-info") )
271 {
272 Load_MetaData(Stream);
273 }
274
275 if( Stream.Get_File(_File + "sg-prj") )
276 {
277 Get_Projection().Load(Stream);
278 }
279 }
280 }
281 else // if( SG_File_Cmp_Extension(File, "sg-pts"/"spc") ) // POINTCLOUD_FILE_FORMAT_Normal
282 {
283 CSG_File Stream(File, SG_FILE_R, true);
284
285 if( (bResult = _Load(Stream)) == true )
286 {
287 Load_MetaData(File);
288
289 Get_Projection().Load(SG_File_Make_Path("", File, "sg-prj"));
290 }
291 }
292
293 //-----------------------------------------------------
295
296 if( bResult )
297 {
298 Set_Modified(false);
299
300 Set_File_Name(File, true);
301
303
304 return( true );
305 }
306
307 SG_UI_Msg_Add(_TL("failed"), false, SG_UI_MSG_STYLE_FAILURE);
308
309 return( false );
310}
311
312//---------------------------------------------------------
313bool CSG_PointCloud::Save(const CSG_String &_File, int Format)
314{
315 if( _File.is_Empty() )
316 {
317 return( *Get_File_Name(false) ? Save(Get_File_Name(false), Format) : false );
318 }
319
321 {
322 Format = SG_File_Cmp_Extension(_File, "sg-pts-z")
325 }
326
327 bool bResult = false;
328
329 CSG_String File(_File);
330
331 switch( Format )
332 {
333 //-----------------------------------------------------
335 {
336 SG_File_Set_Extension(File, "sg-pts-z");
337
338 SG_UI_Msg_Add(CSG_String::Format("%s %s: %s...", _TL("Saving"), _TL("point cloud"), File.c_str()), true);
339
340 CSG_Archive Stream(File, SG_FILE_W);
341
342 CSG_String Name(SG_File_Get_Name(File, false) + ".");
343
344 if( Stream.Add_File(Name + "sg-pts") && _Save(Stream) )
345 {
346 if( Stream.Add_File(Name + "sg-pts-hdr") )
347 {
348 CSG_MetaData Header = _Create_Header(); Header.Save(Stream);
349 }
350
351 if( Stream.Add_File(Name + "sg-info") )
352 {
353 Save_MetaData(Stream);
354 }
355
356 if( Get_Projection().is_Okay() && Stream.Add_File(Name + "sg-prj") )
357 {
358 Get_Projection().Save(Stream);
359 }
360
361 bResult = true;
362 }
363 }
364 break;
365
366 //-----------------------------------------------------
368 {
369 SG_File_Set_Extension(File, "sg-pts");
370
371 SG_UI_Msg_Add(CSG_String::Format("%s %s: %s...", _TL("Saving"), _TL("point cloud"), File.c_str()), true);
372
373 CSG_File Stream(File, SG_FILE_W, true);
374
375 if( _Save(Stream) )
376 {
377 CSG_MetaData Header = _Create_Header(); Header.Save(SG_File_Make_Path("", File, "sg-pts-hdr"));
378
379 Save_MetaData(File);
380
381 if( Get_Projection().is_Okay() )
382 {
383 Get_Projection().Save(SG_File_Make_Path("", File, "sg-prj"));
384 }
385
386 bResult = true;
387 }
388 }
389 break;
390 }
391
392 //-----------------------------------------------------
394
395 if( bResult )
396 {
397 Set_Modified(false);
398
399 Set_File_Name(File, true);
400
402
403 return( true );
404 }
405
406 SG_UI_Msg_Add(_TL("failed"), false, SG_UI_MSG_STYLE_FAILURE);
407
408 return( false );
409}
410
411//---------------------------------------------------------
413{
414 bool bResult = false;
415
416 if( SG_File_Cmp_Extension(File, "sg-pts-z") ) // POINTCLOUD_FILE_FORMAT_Compressed
417 {
418 CSG_Archive Stream(File, SG_FILE_R);
419
420 CSG_String _File(SG_File_Get_Name(File, false) + ".");
421
422 if( Stream.Get_File(_File + "sg-pts-hdr") )
423 {
424 bResult = Header.Load(Stream);
425 }
426 }
427 else // if( SG_File_Cmp_Extension(File, "sg-pts"/"spc") ) // POINTCLOUD_FILE_FORMAT_Normal
428 {
429 bResult = Header.Load(File, SG_T("sg-pts-hdr"));
430 }
431
432 return( bResult );
433}
434
436// //
438
439//---------------------------------------------------------
440bool CSG_PointCloud::_Load(CSG_File &Stream)
441{
442 if( !Stream.is_Reading() )
443 {
444 return( false );
445 }
446
447 //-----------------------------------------------------
448 char ID[6];
449
450 if( !Stream.Read(ID, 6) || strncmp(ID, PC_FILE_VERSION, 5) != 0 )
451 {
452 return( false );
453 }
454
455 int nPointBytes;
456
457 if( !Stream.Read(&nPointBytes, sizeof(int)) || nPointBytes < (int)(3 * sizeof(float)) )
458 {
459 return( false );
460 }
461
462 int nFields;
463
464 if( !Stream.Read(&nFields, sizeof(int)) || nFields < 3 )
465 {
466 return( false );
467 }
468
469 //-----------------------------------------------------
470 Destroy();
471
472 for(int iField=0; iField<nFields; iField++)
473 {
474 TSG_Data_Type Type; int iBuffer; char Name[1024];
475
476 if( !Stream.Read(&Type , sizeof(TSG_Data_Type))
477 || !Stream.Read(&iBuffer, sizeof(int)) || !(iBuffer > 0 && iBuffer < 1024)
478 || !Stream.Read(Name , iBuffer) )
479 {
480 return( false );
481 }
482
483 if( ID[5] == '0' ) // Data Type Definition changed!!!
484 {
485 switch( Type )
486 {
487 default: Type = SG_DATATYPE_Undefined; break;
488 case 1: Type = SG_DATATYPE_Char ; break;
489 case 2: Type = SG_DATATYPE_Short ; break;
490 case 3: Type = SG_DATATYPE_Int ; break;
491 case 4: Type = SG_DATATYPE_Long ; break;
492 case 5: Type = SG_DATATYPE_Float ; break;
493 case 6: Type = SG_DATATYPE_Double ; break;
494 }
495 }
496
497 Name[iBuffer] = '\0';
498
499 if( !_Add_Field(CSG_String((const char *)Name), Type) )
500 {
501 return( false );
502 }
503 }
504
505 //-----------------------------------------------------
506 sLong fLength = Stream.Length();
507
508 while( _Inc_Array() && Stream.Read(m_Cursor + 1, nPointBytes) && SG_UI_Process_Set_Progress((double)Stream.Tell(), (double)fLength) )
509 {
510 // nop
511 }
512
513 _Dec_Array();
514
515 return( true );
516}
517
518//---------------------------------------------------------
519bool CSG_PointCloud::_Save(CSG_File &Stream)
520{
521 if( !Stream.is_Writing() )
522 {
523 return( false );
524 }
525
526 //-----------------------------------------------------
527 int iBuffer, nPointBytes = m_nPointBytes - 1;
528
529 Stream.Write((void *)PC_FILE_VERSION, 6);
530 Stream.Write(&nPointBytes, sizeof(int));
531 Stream.Write(&m_nFields , sizeof(int));
532
533 for(int iField=0; iField<m_nFields; iField++)
534 {
535 Stream.Write(&m_Field_Info[iField]->m_Type, sizeof(TSG_Data_Type));
536
537 iBuffer = (int)m_Field_Info[iField]->m_Name.Length(); if( iBuffer >= 1024 - 1 ) iBuffer = 1024 - 1;
538 Stream.Write(&iBuffer, sizeof(int));
539 Stream.Write((void *)m_Field_Info[iField]->m_Name.b_str(), sizeof(char), iBuffer);
540 }
541
542 _Shape_Flush();
543
545 {
546 Stream.Write(m_Points[i] + 1, nPointBytes);
547 }
548
549 return( true );
550}
551
552//---------------------------------------------------------
553CSG_MetaData CSG_PointCloud::_Create_Header(void) const
554{
555 CSG_MetaData Header;
556
557 Header.Set_Name("PointCloudHeaderFile");
558 Header.Add_Property("Version", "1.0");
559
560 CSG_MetaData *pPoints = Header.Add_Child("Points" );
561 CSG_MetaData *pBBox = Header.Add_Child("BBox" );
562 CSG_MetaData *pNoData = Header.Add_Child("NoData" );
563 CSG_MetaData *pAttr = Header.Add_Child("Attributes");
564
565 pPoints->Add_Property("Value", Get_Count());
566 pBBox ->Add_Property("XMin" , Get_Minimum(0));
567 pBBox ->Add_Property("YMin" , Get_Minimum(1));
568 pBBox ->Add_Property("ZMin" , Get_Minimum(2));
569 pBBox ->Add_Property("XMax" , Get_Maximum(0));
570 pBBox ->Add_Property("YMax" , Get_Maximum(1));
571 pBBox ->Add_Property("ZMax" , Get_Maximum(2));
572 pNoData->Add_Property("Value", Get_NoData_Value());
573 pAttr ->Add_Property("Count", m_nFields);
574
575 for(int iField=0; iField<m_nFields; iField++)
576 {
577 CSG_MetaData *pField = pAttr->Add_Child(CSG_String::Format("Field_%d", iField + 1));
578
579 pField->Add_Property("Name", Get_Field_Name(iField));
580 pField->Add_Property("Type", gSG_Data_Type_Identifier[Get_Field_Type(iField)]);
581 }
582
583 return( Header );
584}
585
586
588// //
589// Assign //
590// //
592
593//---------------------------------------------------------
594bool CSG_PointCloud::Assign(CSG_Data_Object *pObject, bool bProgress)
595{
596 if( pObject->asPointCloud() && CSG_Data_Object::Assign(pObject, bProgress) )
597 {
598 CSG_PointCloud *pPoints = pObject->asPointCloud();
599
600 Create(pPoints);
601
603
604 for(sLong i=0; i<pPoints->m_nRecords && (!bProgress || SG_UI_Process_Set_Progress(i, pPoints->m_nRecords)); i++)
605 {
606 if( _Inc_Array() )
607 {
608 memcpy(m_Points[i] + 1, pPoints->m_Points[i] + 1, m_nPointBytes - 1l);
609 }
610 }
611
612 return( true );
613 }
614
615 return( false );
616}
617
618
620// //
621// Checks //
622// //
624
625//---------------------------------------------------------
627{
628 if( m_nFields == pPointCloud->m_nFields )
629 {
630 for(int iField=0; iField<m_nFields; iField++)
631 {
632 if( Get_Field_Type(iField) != pPointCloud->Get_Field_Type(iField) )
633 {
634 return( false );
635 }
636 }
637
638 return( true );
639 }
640
641 return( false );
642}
643
644
646// //
647// Fields //
648// //
650
651//---------------------------------------------------------
652bool CSG_PointCloud::Add_Field(const CSG_String &Name, TSG_Data_Type Type, int Field)
653{
654 if( m_nFields == 0 ) { _Add_Field(SG_T("X"), m_bXYZPrecDbl ? SG_DATATYPE_Double : SG_DATATYPE_Float); }
655 if( m_nFields == 1 ) { _Add_Field(SG_T("Y"), m_bXYZPrecDbl ? SG_DATATYPE_Double : SG_DATATYPE_Float); }
656 if( m_nFields == 2 ) { _Add_Field(SG_T("Z"), m_bXYZPrecDbl ? SG_DATATYPE_Double : SG_DATATYPE_Float); }
657
658 return( m_nFields >= 3 && _Add_Field(Name, Type, Field) );
659}
660
661//---------------------------------------------------------
662bool CSG_PointCloud::_Add_Field(const SG_Char *Name, TSG_Data_Type Type, int Field)
663{
664 if( !Name || PC_SIZE_TYPE(Type) <= 0 )
665 {
666 return( false );
667 }
668
669 if( Field < 0 || Field > m_nFields )
670 {
671 Field = m_nFields;
672 }
673
674 if( Field < 3 && m_nFields >= 3 )
675 {
676 Field = 3; // (x, y, z) always have to stay in the first place
677 }
678
679 //-----------------------------------------------------
680 int nFieldBytes = PC_SIZE_TYPE(Type);
681
682 if( m_nFields < 1 )
683 {
684 m_nPointBytes = 1;
685 }
686
687 m_nFields++; m_nPointBytes += nFieldBytes;
688
689 //-----------------------------------------------------
690 m_Field_Offset = (int *)SG_Realloc(m_Field_Offset, m_nFields * sizeof(int ));
692
693 for(int i=m_nFields-1; i>Field; i--)
694 {
695 m_Field_Info[i] = m_Field_Info[i - 1];
696 }
697
698 m_Field_Info[Field] = new CSG_Field_Info(Name, Type);
699
700 for(int i=0, Offset=1; i<m_nFields; i++)
701 {
702 m_Field_Offset[i] = Offset; Offset += PC_SIZE_FIELD(i);
703 }
704
705 //-----------------------------------------------------
706 int Offset = m_Field_Offset[Field], nMoveBytes = Field < m_nFields - 1 ? m_nPointBytes - m_Field_Offset[Field + 1] : 0;
707
708 #pragma omp parallel for
709 for(sLong i=0; i<m_nRecords; i++)
710 {
711 m_Points[i] = (char *)SG_Realloc(m_Points[i], m_nPointBytes * sizeof(char));
712
713 if( nMoveBytes > 0 )
714 {
715 memmove(m_Points[i] + Offset + nFieldBytes, m_Points[i] + Offset, nMoveBytes);
716 }
717
718 memset(m_Points[i] + Offset, 0, nFieldBytes);
719 }
720
721 //-----------------------------------------------------
722 m_Shapes.Add_Field(Name, Type, Field);
723
724 Set_Modified();
725
726 return( true );
727}
728
729//---------------------------------------------------------
731{
732 if( Field < 3 || Field >= m_nFields )
733 {
734 return( false );
735 }
736
737 //-----------------------------------------------------
738 int nFieldBytes = PC_SIZE_FIELD(Field);
739
740 m_nFields--; m_nPointBytes -= nFieldBytes;
741
742 //-----------------------------------------------------
743 int Offset = m_Field_Offset[Field], nMoveBytes = Field < m_nFields ? (m_nPointBytes + nFieldBytes) - m_Field_Offset[Field + 1] : 0;
744
745 #pragma omp parallel for
746 for(sLong i=0; i<m_nRecords; i++)
747 {
748 if( nMoveBytes > 0 )
749 {
750 memmove(m_Points[i] + Offset, m_Points[i] + Offset + nFieldBytes, nMoveBytes);
751 }
752
753 m_Points[i] = (char *)SG_Realloc(m_Points[i], m_nPointBytes * sizeof(char));
754 }
755
756 //-----------------------------------------------------
757 delete(m_Field_Info[Field]);
758
759 for(int i=Field, Offset=m_Field_Offset[Field]; i<m_nFields; i++)
760 {
761 m_Field_Info [i] = m_Field_Info[i + 1];
762 m_Field_Offset[i] = Offset; Offset += PC_SIZE_FIELD(i);
763 }
764
766 m_Field_Offset = (int *)SG_Realloc(m_Field_Offset, m_nFields * sizeof(int ));
767
768 //-----------------------------------------------------
769 m_Shapes.Del_Field(Field);
770
771 Set_Modified();
772
773 return( true );
774}
775
776//---------------------------------------------------------
777bool CSG_PointCloud::Mov_Field(int Field, int Position)
778{
779 if( Position < 0 )
780 {
781 Position = 0;
782 }
783 else if( Position >= m_nFields - 1 )
784 {
785 Position = m_nFields - 1;
786 }
787
788 if( Field < 3 || Field >= m_nFields || Field == Position )
789 {
790 return( false );
791 }
792
793 //-----------------------------------------------------
794 if( Position > Field )
795 {
796 Position++;
797 }
798
799 if( !Add_Field(m_Field_Info[Field]->m_Name, m_Field_Info[Field]->m_Type, Position) )
800 {
801 return( false );
802 }
803
804 if( Position < Field )
805 {
806 Field++;
807 }
808
809 size_t Size = PC_SIZE_FIELD(Field);
810
811 #pragma omp parallel for
812 for(sLong i=0; i<m_nRecords; i++)
813 {
814 memcpy(m_Points[i] + m_Field_Offset[Position], m_Points[i] + m_Field_Offset[Field], Size);
815 }
816
817 if( !Del_Field(Field) )
818 {
819 return( false );
820 }
821
822 //-----------------------------------------------------
823 return( true );
824}
825
826
828// //
830
831//---------------------------------------------------------
836//---------------------------------------------------------
837int CSG_PointCloud::Get_Field_Length(int Field, int Encoding) const
838{
839 size_t Length = 0;
840
841 if( Field >= 0 && Field < m_nFields )
842 {
843 Length = (Field + 1 >= m_nFields ? m_nPointBytes : m_Field_Offset[Field + 1]) - m_Field_Offset[Field];
844 }
845
846 return( (int)Length );
847}
848
849//---------------------------------------------------------
851{
852 if( iField < 3 || iField >= m_nFields )
853 {
854 return( false );
855 }
856
857 if( Type == m_Field_Info[iField]->m_Type )
858 {
859 return( true );
860 }
861
862 //-----------------------------------------------------
863 Add_Field(Get_Field_Name(iField), Type, iField);
864
865 #pragma omp parallel for
866 for(sLong i=0; i<m_nRecords; i++)
867 {
868 Set_Value(i, iField, Get_Value(i, iField + 1));
869 }
870
871 Del_Field(iField + 1);
872
873 //-----------------------------------------------------
874 m_Shapes.Set_Field_Type(iField, Type);
875
876 Set_Modified();
877
878 return( true );
879}
880
881
883// //
885
886//---------------------------------------------------------
887bool CSG_PointCloud::_Set_Field_Value(char *Record, int Field, const SG_Char *Value)
888{
889 if( Record && Field >= 0 && Field < m_nFields && Value )
890 {
891 CSG_String s(Value);
892
893 switch( m_Field_Info[Field]->m_Type )
894 {
895 case SG_DATATYPE_Byte :
896 case SG_DATATYPE_Char :
897 case SG_DATATYPE_Word :
898 case SG_DATATYPE_Short :
899 case SG_DATATYPE_DWord :
900 case SG_DATATYPE_Color :
901 case SG_DATATYPE_Int :
902 case SG_DATATYPE_ULong :
903 case SG_DATATYPE_Long : { sLong v; return( s.asLong (v) && _Set_Field_Value(Record, Field, v) ); }
904
905 case SG_DATATYPE_Float :
906 case SG_DATATYPE_Double: { double v; return( s.asDouble(v) && _Set_Field_Value(Record, Field, v) ); }
907
908 case SG_DATATYPE_Date :
910 Record += m_Field_Offset[Field];
911 memset(Record, 0, PC_SIZE_STRING);
912 memcpy(Record, s.b_str(), s.Length() > PC_SIZE_STRING ? PC_SIZE_STRING : s.Length());
913 break;
914
915 default : return( false );
916 }
917
918 return( true );
919 }
920
921 return( false );
922}
923
924//---------------------------------------------------------
925bool CSG_PointCloud::_Set_Field_Value(char *Record, int Field, const sLong &Value)
926{
927 if( Record && Field >= 0 && Field < m_nFields )
928 {
929 Record += m_Field_Offset[Field];
930
931 switch( m_Field_Info[Field]->m_Type )
932 {
933 case SG_DATATYPE_Byte : *((BYTE *)Record) = (BYTE )Value ; break;
934 case SG_DATATYPE_Char : *((char *)Record) = (char )Value ; break;
935 case SG_DATATYPE_Word : *((WORD *)Record) = (WORD )Value ; break;
936 case SG_DATATYPE_Short : *((short *)Record) = (short )Value ; break;
937 case SG_DATATYPE_DWord : *((DWORD *)Record) = (DWORD )Value ; break;
938 case SG_DATATYPE_Color : *((DWORD *)Record) = (DWORD )Value ; break;
939 case SG_DATATYPE_Int : *((int *)Record) = (int )Value ; break;
940 case SG_DATATYPE_ULong : *((uLong *)Record) = (uLong )Value ; break;
941 case SG_DATATYPE_Long : *((sLong *)Record) = (sLong )Value ; break;
942 case SG_DATATYPE_Float : *((float *)Record) = (float )Value ; break;
943 case SG_DATATYPE_Double: *((double *)Record) = (double)Value ; break;
944
945 case SG_DATATYPE_String: { CSG_String s; s.Printf("%lld", Value); return( _Set_Field_Value(Record, Field, s) ); }
946
947 default : return( false );
948 }
949
950 m_Field_Info[Field]->Reset_Statistics();
951
952 Set_Modified();
953
954 if( Field < 3 )
955 {
956 Set_Update_Flag(); // extent might have changed
957 }
958
959 return( true );
960 }
961
962 return( false );
963}
964
965//---------------------------------------------------------
966bool CSG_PointCloud::_Set_Field_Value(char *Record, int Field, const double &Value)
967{
968 if( Record && Field >= 0 && Field < m_nFields )
969 {
970 Record += m_Field_Offset[Field];
971
972 switch( m_Field_Info[Field]->m_Type )
973 {
974 case SG_DATATYPE_Byte : *((BYTE *)Record) = (BYTE )Value ; break;
975 case SG_DATATYPE_Char : *((char *)Record) = (char )Value ; break;
976 case SG_DATATYPE_Word : *((WORD *)Record) = (WORD )Value ; break;
977 case SG_DATATYPE_Short : *((short *)Record) = (short )Value ; break;
978 case SG_DATATYPE_DWord : *((DWORD *)Record) = (DWORD )Value ; break;
979 case SG_DATATYPE_Int : *((int *)Record) = (int )Value ; break;
980 case SG_DATATYPE_Long : *((sLong *)Record) = (sLong )Value ; break;
981 case SG_DATATYPE_ULong : *((uLong *)Record) = (uLong )Value ; break;
982 case SG_DATATYPE_Float : *((float *)Record) = (float )Value ; break;
983 case SG_DATATYPE_Double: *((double *)Record) = (double)Value ; break;
984 case SG_DATATYPE_Color : *((DWORD *)Record) = (DWORD )Value ; break;
985
986 case SG_DATATYPE_String: { CSG_String s; s.Printf("%f", Value); return( _Set_Field_Value(Record, Field, s) ); }
987
988 default : return( false );
989 }
990
991 m_Field_Info[Field]->Reset_Statistics();
992
993 Set_Modified();
994
995 if( Field < 3 )
996 {
997 Set_Update_Flag(); // extent might have changed
998 }
999
1000 return( true );
1001 }
1002
1003 return( false );
1004}
1005
1006//---------------------------------------------------------
1007double CSG_PointCloud::_Get_Field_Value(char *Record, int Field) const
1008{
1009 double Value; return( _Get_Field_Value(Record, Field, Value) ? Value : Get_NoData_Value() );
1010}
1011
1012//---------------------------------------------------------
1013bool CSG_PointCloud::_Get_Field_Value(char *Record, int Field, CSG_String &Value) const
1014{
1015 if( Record && Field >= 0 && Field < m_nFields )
1016 {
1017 switch( m_Field_Info[Field]->m_Type )
1018 {
1019 case SG_DATATYPE_Byte :
1020 case SG_DATATYPE_Word :
1021 case SG_DATATYPE_DWord :
1022 case SG_DATATYPE_Color :
1023 case SG_DATATYPE_ULong : { sLong v; if( _Get_Field_Value(Record, Field, v) ) { Value.Printf("%llu", (uLong)v); return( true ); } } break;
1024
1025 case SG_DATATYPE_Char :
1026 case SG_DATATYPE_Short :
1027 case SG_DATATYPE_Int :
1028 case SG_DATATYPE_Long : { sLong v; if( _Get_Field_Value(Record, Field, v) ) { Value.Printf("%lld", (sLong)v); return( true ); } } break;
1029
1030 case SG_DATATYPE_Float :
1031 case SG_DATATYPE_Double: { double v; if( _Get_Field_Value(Record, Field, v) ) { Value.Printf("%f" , (double)v); return( true ); } } break;
1032
1033 case SG_DATATYPE_Date :
1034 case SG_DATATYPE_String:
1035 {
1036 char s[PC_SIZE_STRING + 1];
1037 memcpy(s, Record + m_Field_Offset[Field], PC_SIZE_STRING);
1038 s[PC_SIZE_STRING] = '\0';
1039
1040 Value = s;
1041
1042 return( true );
1043 }
1044
1045 default : break;
1046 }
1047 }
1048
1049 return( false );
1050}
1051
1052//---------------------------------------------------------
1053bool CSG_PointCloud::_Get_Field_Value(char *Record, int Field, sLong &Value) const
1054{
1055 if( Record && Field >= 0 && Field < m_nFields )
1056 {
1057 Record += m_Field_Offset[Field];
1058
1059 switch( m_Field_Info[Field]->m_Type )
1060 {
1061 case SG_DATATYPE_Byte : Value = (sLong)*((BYTE *)Record); return( true );
1062 case SG_DATATYPE_Char : Value = (sLong)*((char *)Record); return( true );
1063 case SG_DATATYPE_Word : Value = (sLong)*((WORD *)Record); return( true );
1064 case SG_DATATYPE_Short : Value = (sLong)*((short *)Record); return( true );
1065 case SG_DATATYPE_DWord : Value = (sLong)*((DWORD *)Record); return( true );
1066 case SG_DATATYPE_Int : Value = (sLong)*((int *)Record); return( true );
1067 case SG_DATATYPE_Long : Value = (sLong)*((sLong *)Record); return( true );
1068 case SG_DATATYPE_ULong : Value = (sLong)*((uLong *)Record); return( true );
1069 case SG_DATATYPE_Float : Value = (sLong)*((float *)Record); return( true );
1070 case SG_DATATYPE_Double: Value = (sLong)*((double *)Record); return( true );
1071 case SG_DATATYPE_Color : Value = (sLong)*((DWORD *)Record); return( true );
1072 case SG_DATATYPE_String: Value = (sLong) atoll(Record); return( true );
1073
1074 default : break;
1075 }
1076 }
1077
1078 return( false );
1079}
1080
1081//---------------------------------------------------------
1082bool CSG_PointCloud::_Get_Field_Value(char *Record, int Field, double &Value) const
1083{
1084 if( Record && Field >= 0 && Field < m_nFields )
1085 {
1086 Record += m_Field_Offset[Field];
1087
1088 switch( m_Field_Info[Field]->m_Type )
1089 {
1090 case SG_DATATYPE_Byte : Value = (double)*((BYTE *)Record); return( true );
1091 case SG_DATATYPE_Char : Value = (double)*((char *)Record); return( true );
1092 case SG_DATATYPE_Word : Value = (double)*((WORD *)Record); return( true );
1093 case SG_DATATYPE_Short : Value = (double)*((short *)Record); return( true );
1094 case SG_DATATYPE_DWord : Value = (double)*((DWORD *)Record); return( true );
1095 case SG_DATATYPE_Int : Value = (double)*((int *)Record); return( true );
1096 case SG_DATATYPE_Long : Value = (double)*((sLong *)Record); return( true );
1097 case SG_DATATYPE_ULong : Value = (double)*((uLong *)Record); return( true );
1098 case SG_DATATYPE_Float : Value = (double)*((float *)Record); return( true );
1099 case SG_DATATYPE_Double: Value = (double)*((double *)Record); return( true );
1100 case SG_DATATYPE_Color : Value = (double)*((DWORD *)Record); return( true );
1101 case SG_DATATYPE_String: Value = (double) atof(Record); return( true );
1102
1103 default : break;
1104 }
1105 }
1106
1107 return( false );
1108}
1109
1110
1112// //
1113// //
1114// //
1116
1117//---------------------------------------------------------
1119{
1120 TSG_Point_3D p;
1121
1122 if( m_Cursor )
1123 {
1124 p.x = _Get_Field_Value(m_Cursor, 0);
1125 p.y = _Get_Field_Value(m_Cursor, 1);
1126 p.z = _Get_Field_Value(m_Cursor, 2);
1127 }
1128 else
1129 {
1130 p.x = p.y = p.z = 0.;
1131 }
1132
1133 return( p );
1134}
1135
1136//---------------------------------------------------------
1138{
1139 TSG_Point_3D p;
1140
1141 if( Index >= 0 && Index < m_nRecords )
1142 {
1143 char *pPoint = m_Points[Index];
1144
1145 p.x = _Get_Field_Value(pPoint, 0);
1146 p.y = _Get_Field_Value(pPoint, 1);
1147 p.z = _Get_Field_Value(pPoint, 2);
1148 }
1149 else
1150 {
1151 p.x = p.y = p.z = 0.;
1152 }
1153
1154 return( p );
1155}
1156
1157//---------------------------------------------------------
1159{
1160 return( _Set_Field_Value(m_Cursor, 0, Point.x)
1161 && _Set_Field_Value(m_Cursor, 1, Point.y)
1162 && _Set_Field_Value(m_Cursor, 2, Point.z)
1163 );
1164}
1165
1166//---------------------------------------------------------
1168{
1169 if( Index >= 0 && Index < m_nRecords )
1170 {
1171 return( _Set_Field_Value(m_Points[Index], 0, Point.x)
1172 && _Set_Field_Value(m_Points[Index], 1, Point.y)
1173 && _Set_Field_Value(m_Points[Index], 2, Point.z)
1174 );
1175 }
1176
1177 return( false );
1178}
1179
1180
1182// //
1183// //
1184// //
1186
1187//---------------------------------------------------------
1188bool CSG_PointCloud::Add_Point(double x, double y, double z)
1189{
1190 if( _Inc_Array() )
1191 {
1192 _Set_Field_Value(m_Cursor, 0, x);
1193 _Set_Field_Value(m_Cursor, 1, y);
1194 _Set_Field_Value(m_Cursor, 2, z);
1195
1196 Set_Modified();
1199
1200 return( true );
1201 }
1202
1203 return( false );
1204}
1205
1206//---------------------------------------------------------
1208{
1209 return( Add_Point(Point.x, Point.y, Point.z) );
1210}
1211
1212//---------------------------------------------------------
1214{
1215 if( Index >= 0 && Index < m_nRecords )
1216 {
1217 if( is_Selected(Index) )
1218 {
1219 Select(Index, true);
1220 }
1221
1222 m_Cursor = m_Points[Index];
1223
1224 for(sLong i=Index, j=Index+1; j<m_nRecords; i++, j++)
1225 {
1226 m_Points[i] = m_Points[j];
1227 }
1228
1229 m_Points[m_nRecords - 1] = m_Cursor;
1230
1231 m_Cursor = NULL;
1232
1233 _Dec_Array();
1234
1235 Set_Modified();
1238
1239 return( true );
1240 }
1241
1242 return( false );
1243}
1244
1245//---------------------------------------------------------
1247{
1248 for(sLong i=0; i<m_nRecords; i++)
1249 {
1250 SG_Free(m_Points[i]);
1251 }
1252
1253 m_Array_Points.Set_Array(0);
1254
1255 m_nRecords = 0;
1256 m_Points = NULL;
1257 m_Cursor = NULL;
1258
1259 m_Selection.Set_Array(0);
1260
1261 Set_Modified();
1264
1265 return( true );
1266}
1267
1268
1270// //
1271// //
1272// //
1274
1275//---------------------------------------------------------
1276bool CSG_PointCloud::_Inc_Array(void)
1277{
1278 if( m_nFields > 0 && m_Array_Points.Set_Array(m_nRecords + 1, (void **)&m_Points) )
1279 {
1280 m_Points[m_nRecords++] = m_Cursor = (char *)SG_Calloc(m_nPointBytes, sizeof(char));
1281
1282 return( true );
1283 }
1284
1285 return( false );
1286}
1287
1288//---------------------------------------------------------
1289bool CSG_PointCloud::_Dec_Array(void)
1290{
1291 if( m_nRecords > 0 )
1292 {
1293 m_nRecords --;
1294
1295 m_Cursor = NULL;
1296
1297 SG_Free(m_Points[m_nRecords]);
1298
1299 m_Array_Points.Set_Array(m_nRecords, (void **)&m_Points);
1300 }
1301
1302 return( true );
1303}
1304
1305
1307// //
1308// Statistics //
1309// //
1311
1312//---------------------------------------------------------
1314{
1315 if( m_nFields >= 2 )
1316 {
1317 _Shape_Flush();
1318
1319 for(int iField=0; iField<m_nFields; iField++)
1320 {
1321 m_Field_Info[iField]->Reset_Statistics();
1322 }
1323
1325
1326 m_ZMin = Get_Minimum(2);
1327 m_ZMax = Get_Maximum(2);
1328 }
1329
1330 return( true );
1331}
1332
1333//---------------------------------------------------------
1335{
1336 if( Field >= 3 ) // attributes, else => always get full statistics for x, y, z coordinates!
1337 {
1338 return( CSG_Table::_Stats_Update(Field) );
1339 }
1340
1341 if( Field < 0 || m_nRecords < 1 )
1342 {
1343 return( false );
1344 }
1345
1346 CSG_Simple_Statistics &Statistics = m_Field_Info[Field]->m_Statistics;
1347
1348 if( Statistics.is_Evaluated() )
1349 {
1350 return( true );
1351 }
1352
1353 char **pPoint = m_Points;
1354
1355 for(sLong i=0; i<m_nRecords; i++, pPoint++)
1356 {
1357 Statistics += _Get_Field_Value(*pPoint, Field);
1358 }
1359
1360 return( Statistics.Evaluate() ); // evaluate! prevent values to be added more than once!
1361}
1362
1363
1365// //
1366// //
1367// //
1369
1370//---------------------------------------------------------
1372{
1373 return( Create(Get_File_Name(false)) );
1374}
1375
1376//---------------------------------------------------------
1378{
1379 return( SG_File_Delete(Get_File_Name(false)) );
1380}
1381
1382
1384// //
1385// //
1386// //
1388
1389//---------------------------------------------------------
1390CSG_Shape * CSG_PointCloud::_Shape_Get(sLong Index)
1391{
1392 SG_UI_Progress_Lock(true);
1393
1394 CSG_Shape *pShape = m_Shapes.Get_Shape(SG_OMP_Get_Thread_Num());
1395
1396 if( pShape->is_Modified() && pShape->m_Index >= 0 && pShape->m_Index < m_nRecords )
1397 {
1398 char *Point = m_Points[pShape->m_Index];
1399
1400 for(int iField=0; iField<m_nFields; iField++)
1401 {
1402 switch( Get_Field_Type(iField) )
1403 {
1404 default : _Set_Field_Value(Point, iField, pShape->asDouble(iField)); break;
1405
1406 case SG_DATATYPE_Long : *(sLong *)(Point + m_Field_Offset[iField]) = pShape->asLong (iField); break;
1407 case SG_DATATYPE_ULong : *(uLong *)(Point + m_Field_Offset[iField]) = pShape->asULong(iField); break;
1408
1409 case SG_DATATYPE_Date :
1410 case SG_DATATYPE_String: _Set_Field_Value(Point, iField, pShape->asString(iField)); break;
1411 }
1412 }
1413
1414 Set_Value(0, pShape->Get_Point().x);
1415 Set_Value(1, pShape->Get_Point().y);
1416 Set_Value(2, pShape->Get_Z () );
1417 }
1418
1419 if( Index >= 0 && Index < m_nRecords )
1420 {
1421 char *Point = m_Points[Index];
1422
1423 for(int iField=0; iField<m_nFields; iField++)
1424 {
1425 switch( Get_Field_Type(iField) )
1426 {
1427 default : pShape->Set_Value(iField, _Get_Field_Value(Point, iField)); break;
1428
1429 case SG_DATATYPE_DWord : pShape->Set_Value(iField, *(DWORD *)(Point + m_Field_Offset[iField])); break;
1430 case SG_DATATYPE_Long : pShape->Set_Value(iField, *(sLong *)(Point + m_Field_Offset[iField])); break;
1431 case SG_DATATYPE_ULong : pShape->Set_Value(iField, *(uLong *)(Point + m_Field_Offset[iField])); break;
1432
1433 case SG_DATATYPE_Date :
1434 case SG_DATATYPE_String: { CSG_String s; _Get_Field_Value(Point, iField, s); pShape->Set_Value(iField, s); break; }
1435 }
1436 }
1437
1438 pShape->Set_Point(Get_Point(Index));
1439 pShape->Set_Selected(is_Selected(Index));
1440 pShape->Set_Modified(false);
1441
1442 pShape->m_Index = Index;
1443 }
1444 else
1445 {
1446 pShape->m_Index = -1;
1447 }
1448
1449 SG_UI_Progress_Lock(false);
1450
1451 return( pShape->m_Index >= 0 ? pShape : NULL );
1452}
1453
1454//---------------------------------------------------------
1455void CSG_PointCloud::_Shape_Flush(void)
1456{
1457 for(sLong i=0; i<m_Shapes.Get_Count(); i++)
1458 {
1459 _Shape_Get(m_Shapes[i].m_Index); m_Shapes[i].m_Index = -1;
1460 }
1461}
1462
1463//---------------------------------------------------------
1465{
1466 return( ((CSG_PointCloud *)this)->_Shape_Get(Index) );
1467}
1468
1469
1471// //
1472// //
1473// //
1475
1476//---------------------------------------------------------
1481//---------------------------------------------------------
1482sLong CSG_PointCloud::Get_Point(const CSG_Point &Point, double Epsilon)
1483{
1484 sLong Index = -1; CSG_Rect r(Point.x - Epsilon, Point.y - Epsilon, Point.x + Epsilon, Point.y + Epsilon);
1485
1487 {
1488 double Distance = -1.;
1489
1490 for(sLong i=0; i<m_nRecords; i++)
1491 {
1492 double x = Get_X(i), y = Get_Y(i);
1493
1494 if( r.Contains(x, y) )
1495 {
1496 if( Index < 0 || Distance > SG_Get_Distance(Point.x, Point.y, x, y) )
1497 {
1498 Index = i; Distance = SG_Get_Distance(Point.x, Point.y, x, y);
1499 }
1500 }
1501 }
1502 }
1503
1504 return( Index );
1505}
1506
1507//---------------------------------------------------------
1508CSG_Shape * CSG_PointCloud::Get_Shape(const CSG_Point &Point, double Epsilon)
1509{
1510 sLong Index = Get_Point(Point, Epsilon);
1511
1512 return( Index < 0 ? NULL : CSG_Shapes::Get_Shape(Index) );
1513}
1514
1515//---------------------------------------------------------
1517{
1518 return( NULL );
1519}
1520
1521//---------------------------------------------------------
1526
1527//---------------------------------------------------------
1529{
1530 Add_Point(0., 0., 0.);
1531
1532 if( pCopy && (mCopy == SHAPE_COPY_ATTR || mCopy == SHAPE_COPY) )
1533 {
1534 for(int iField=0; iField<m_nFields && iField<pCopy->Get_Table()->Get_Field_Count(); iField++)
1535 {
1536 if( Get_Field_Type(iField) == pCopy->Get_Table()->Get_Field_Type(iField) )
1537 {
1539 {
1540 Set_Value(iField, pCopy->asDouble(iField));
1541 }
1542 else
1543 {
1544 Set_Value(iField, pCopy->asString(iField));
1545 }
1546 }
1547 }
1548 }
1549
1550 return( _Shape_Get(m_nRecords - 1) );
1551}
1552
1553
1555// //
1556// //
1557// //
1559
1560//---------------------------------------------------------
1561bool CSG_PointCloud::Select(sLong Index, bool bInvert)
1562{
1563 if( !bInvert && Get_Selection_Count() > 0 )
1564 {
1565 for(sLong i=0; i<Get_Selection_Count(); i++)
1566 {
1568 }
1569
1570 m_Selection.Destroy();
1571 }
1572
1573 if( Set_Cursor(Index) )
1574 {
1575 if( (m_Cursor[0] & SG_TABLE_REC_FLAG_Selected) == 0 ) // select
1576 {
1577 if( _Add_Selection(Index) )
1578 {
1579 m_Cursor[0] |= SG_TABLE_REC_FLAG_Selected;
1580
1581 return( true );
1582 }
1583 }
1584 else // deselect
1585 {
1586 if( _Del_Selection(Index) )
1587 {
1588 m_Cursor[0] &= ~SG_TABLE_REC_FLAG_Selected;
1589
1590 return( true );
1591 }
1592 }
1593 }
1594
1595 return( false );
1596}
1597
1598//---------------------------------------------------------
1599bool CSG_PointCloud::Select(CSG_Table_Record *pShape, bool bInvert)
1600{
1601 return( CSG_Table::Select(pShape, bInvert) );
1602}
1603
1604//---------------------------------------------------------
1605bool CSG_PointCloud::Select(const TSG_Rect &Extent, bool bInvert)
1606{
1607 if( !bInvert ) // clear selection
1608 {
1609 Select(-1, false);
1610 }
1611
1612 if( Get_Extent().Intersects(Extent) != INTERSECTION_None )
1613 {
1614 for(sLong i=0; i<m_nRecords; i++)
1615 {
1616 Set_Cursor(i);
1617
1618 if( Extent.xMin <= Get_X() && Get_X() <= Extent.xMax
1619 && Extent.yMin <= Get_Y() && Get_Y() <= Extent.yMax )
1620 {
1621 Select(i, true);
1622 }
1623 }
1624 }
1625
1626 return( Get_Selection_Count() > 0 );
1627}
1628
1629//---------------------------------------------------------
1630bool CSG_PointCloud::Select(const TSG_Point &Point, bool bInvert)
1631{
1632 return( Select(CSG_Rect(Point.x, Point.y, Point.x, Point.y), bInvert) );
1633}
1634
1635
1637// //
1639
1640//---------------------------------------------------------
1642{
1643 return( Index >= 0 && Index < m_nRecords && (m_Points[Index][0] & SG_TABLE_REC_FLAG_Selected) != 0 );
1644}
1645
1646
1648// //
1650
1651//---------------------------------------------------------
1653{
1654 return( Index < Get_Selection_Count() ? ((CSG_PointCloud *)this)->_Shape_Get(Get_Selection_Index(Index)) : NULL );
1655}
1656
1657//---------------------------------------------------------
1659{
1660 if( Get_Selection_Count() > 0 && Set_Cursor((int)Get_Selection_Index(0)) )
1661 {
1662 TSG_Rect r;
1663
1664 r.xMin = r.xMax = Get_X();
1665 r.yMin = r.yMax = Get_Y();
1666
1667 for(sLong i=1; i<Get_Selection_Count(); i++)
1668 {
1670 {
1671 if( Get_X() < r.xMin ) { r.xMin = Get_X(); } else if( Get_X() > r.xMax ) { r.xMax = Get_X(); }
1672 if( Get_Y() < r.yMin ) { r.yMin = Get_Y(); } else if( Get_Y() > r.yMax ) { r.yMax = Get_Y(); }
1673 }
1674 }
1675
1676 m_Extent_Selected.Assign(r);
1677 }
1678 else
1679 {
1680 m_Extent_Selected.Assign(0., 0., 0., 0.);
1681 }
1682
1683 return( m_Extent_Selected );
1684}
1685
1686
1688// //
1690
1691//---------------------------------------------------------
1693{
1694 sLong n = 0;
1695
1696 if( Get_Selection_Count() > 0 )
1697 {
1698 m_Selection.Set_Array(0);
1699
1700 m_Cursor = NULL;
1701
1702 for(sLong i=0; i<m_nRecords; i++)
1703 {
1704 if( (m_Points[i][0] & SG_TABLE_REC_FLAG_Selected) != 0 )
1705 {
1706 SG_Free(m_Points[i]);
1707 }
1708 else
1709 {
1710 if( n < i )
1711 {
1712 m_Points[n] = m_Points[i];
1713 }
1714
1715 n++;
1716 }
1717 }
1718
1719 m_Array_Points.Set_Array(m_nRecords = n, (void **)&m_Points);
1720
1721 Set_Modified();
1724 }
1725
1726 return( n );
1727}
1728
1729//---------------------------------------------------------
1731{
1732 if( m_Selection.Set_Array(m_nRecords - Get_Selection_Count()) )
1733 {
1734 char **pPoint = m_Points;
1735
1736 for(sLong i=0, n=0; i<m_nRecords && n<Get_Selection_Count(); i++, pPoint++)
1737 {
1738 if( ((*pPoint)[0] & SG_TABLE_REC_FLAG_Selected) != 0 )
1739 {
1740 (*pPoint)[0] &= ~SG_TABLE_REC_FLAG_Selected;
1741 }
1742 else
1743 {
1744 (*pPoint)[0] |= SG_TABLE_REC_FLAG_Selected;
1745
1746 _Set_Selection(i, n++);
1747 }
1748 }
1749 }
1750
1751 return( Get_Selection_Count() );
1752}
1753
1754
1756// //
1757// //
1758// //
1760
1761//---------------------------------------------------------
1763{
1764 m_Points[m_nRecords++] = (char *)SG_Calloc(m_nPointBytes, sizeof(char));
1765
1766 if( Get_Count() > 0 && Get_Count() == Index.Get_Count() )
1767 {
1768 char **Points = (char **)SG_Malloc(m_nBuffer * sizeof(char *)); memcpy(Points, m_Points, Get_Count());
1769
1770 for(sLong i=0; i<Get_Count(); i++)
1771 {
1772 m_Points[i] = Points[Index[i]];
1773 }
1774
1775 SG_Free(Points);
1776
1777 Del_Index(); m_Cursor = NULL;
1778
1779 return( true );
1780 }
1781
1782 return( false );
1783}
1784
1785
1787// //
1788// //
1789// //
1791
1792//---------------------------------------------------------
void SG_UI_Msg_Add(const char *Message, bool bNewLine, TSG_UI_MSG_STYLE Style)
bool SG_UI_Process_Set_Ready(void)
bool SG_UI_Process_Set_Progress(int Position, int Range)
int SG_UI_Progress_Lock(bool bOn)
int SG_OMP_Get_Max_Num_Procs(void)
Definition api_core.cpp:111
int SG_OMP_Get_Thread_Num(void)
Definition api_core.cpp:112
bool SG_Data_Type_is_Numeric(TSG_Data_Type Type)
Definition api_core.cpp:198
@ SG_UI_MSG_STYLE_FAILURE
Definition api_core.h:1635
@ SG_UI_MSG_STYLE_SUCCESS
Definition api_core.h:1634
unsigned long long uLong
Definition api_core.h:159
SAGA_API_DLL_EXPORT bool SG_File_Cmp_Extension(const CSG_String &File, const CSG_String &Extension)
SAGA_API_DLL_EXPORT void * SG_Malloc(size_t size)
signed long long sLong
Definition api_core.h:158
#define SG_T(s)
Definition api_core.h:537
SAGA_API_DLL_EXPORT void SG_Free(void *memblock)
SAGA_API_DLL_EXPORT CSG_String SG_File_Make_Path(const CSG_String &Directory, const CSG_String &Name)
SAGA_API_DLL_EXPORT bool SG_File_Delete(const CSG_String &FileName)
SAGA_API_DLL_EXPORT CSG_String SG_File_Get_Name(const CSG_String &full_Path, bool bExtension)
SAGA_API_DLL_EXPORT void * SG_Realloc(void *memblock, size_t size)
SAGA_API_DLL_EXPORT void * SG_Calloc(size_t num, size_t size)
const char gSG_Data_Type_Identifier[][32]
Definition api_core.h:1089
SAGA_API_DLL_EXPORT bool SG_File_Set_Extension(CSG_String &File, const CSG_String &Extension)
TSG_Data_Type
Definition api_core.h:1043
@ SG_DATATYPE_Long
Definition api_core.h:1052
@ SG_DATATYPE_Byte
Definition api_core.h:1045
@ SG_DATATYPE_Short
Definition api_core.h:1048
@ SG_DATATYPE_Word
Definition api_core.h:1047
@ SG_DATATYPE_ULong
Definition api_core.h:1051
@ SG_DATATYPE_Float
Definition api_core.h:1053
@ SG_DATATYPE_Undefined
Definition api_core.h:1059
@ SG_DATATYPE_Double
Definition api_core.h:1054
@ SG_DATATYPE_Color
Definition api_core.h:1057
@ SG_DATATYPE_Int
Definition api_core.h:1050
@ SG_DATATYPE_Char
Definition api_core.h:1046
@ SG_DATATYPE_String
Definition api_core.h:1055
@ SG_DATATYPE_DWord
Definition api_core.h:1049
@ SG_DATATYPE_Date
Definition api_core.h:1056
#define SG_Char
Definition api_core.h:536
#define _TL(s)
Definition api_core.h:1618
@ SG_FILE_W
Definition api_core.h:1161
@ SG_FILE_R
Definition api_core.h:1160
bool Add_File(const SG_Char *Name, bool bBinary=true)
Definition api_file.cpp:715
bool Get_File(const SG_Char *Name)
Definition api_file.cpp:775
bool Set_Array(sLong nValues, bool bShrink=true)
void Set_Update_Flag(bool bOn=true)
Definition dataobject.h:288
bool Save_MetaData(const CSG_String &FileName)
double Get_NoData_Value(bool bUpper=false) const
Definition dataobject.h:256
const SG_Char * Get_File_Name(bool bNative=true) const
bool Load_MetaData(const CSG_String &FileName)
virtual bool Destroy(void)
class CSG_PointCloud * asPointCloud(bool bPolymorph=false) const
virtual bool Set_NoData_Value(double Value)
virtual bool Assign(CSG_Data_Object *pObject, bool bProgress=false)
CSG_Projection & Get_Projection(void)
void Set_File_Name(const CSG_String &FileName)
sLong Length(void) const
Definition api_file.cpp:230
sLong Tell(void) const
Definition api_file.cpp:265
size_t Write(void *Buffer, size_t Size, size_t Count=1) const
Definition api_file.cpp:382
size_t Read(void *Buffer, size_t Size, size_t Count=1) const
Definition api_file.cpp:338
bool is_Writing(void) const
Definition api_core.h:1197
bool is_Reading(void) const
Definition api_core.h:1196
sLong Get_Count(void) const
Definition mat_tools.h:241
bool Save(const CSG_String &File, const SG_Char *Extension=NULL) const
Definition metadata.cpp:904
void Set_Name(const CSG_String &Name)
Definition metadata.h:136
CSG_MetaData * Add_Child(void)
Definition metadata.cpp:166
bool Load(const CSG_String &File, const SG_Char *Extension=NULL)
Definition metadata.cpp:809
bool Add_Property(const CSG_String &Name, const CSG_String &Value)
Definition metadata.cpp:582
bool Del_Point(sLong Index)
TSG_Point_3D Get_Point(void) const
bool Set_Cursor(sLong Index)
Definition pointcloud.h:165
virtual bool Set_Point(const TSG_Point_3D &Point)
virtual bool Destroy(void)
bool Add_Point(double x, double y, double z)
virtual CSG_Shape * Add_Shape(CSG_Table_Record *pCopy=NULL, TSG_ADD_Shape_Copy_Mode mCopy=SHAPE_COPY)
virtual bool Save(const CSG_String &File, int Format=0)
virtual bool Del_Field(int Field)
virtual const CSG_Rect & Get_Selection_Extent(void)
virtual CSG_Table_Record * Get_Record(sLong Index) const
virtual CSG_Table_Record * Ins_Record(sLong Index, CSG_Table_Record *pCopy=NULL)
virtual void Set_Modified(bool bModified=true)
Definition pointcloud.h:288
virtual CSG_Shape * Get_Shape(const CSG_Point &Point, double Epsilon=0.)
virtual bool Assign(CSG_Data_Object *pSource, bool bProgress=false)
bool is_Compatible(CSG_PointCloud *pPointCloud) const
virtual double Get_Value(int Field) const
Definition pointcloud.h:180
virtual bool Set_Value(int Field, const BYTE &Value)
Definition pointcloud.h:205
virtual bool On_Update(void)
virtual bool Sort(const CSG_Index &Index)
virtual bool Mov_Field(int Field, int Position)
virtual sLong Inv_Selection(void)
virtual bool On_Delete(void)
virtual ~CSG_PointCloud(void)
static bool Get_Header_Content(const CSG_String &FileName, CSG_MetaData &Header)
virtual CSG_Table_Record * Add_Record(CSG_Table_Record *pCopy=NULL)
virtual void _On_Construction(void)
virtual bool is_Selected(sLong Index) const
bool Del_Points(void)
virtual bool Add_Field(const CSG_String &Name, TSG_Data_Type Type, int Field=-1)
virtual bool On_Reload(void)
virtual CSG_Table_Record * Get_Selection(sLong Index=0) const
virtual int Get_Field_Length(int Field, int Encoding=SG_FILE_ENCODING_UNDEFINED) const
double Get_X(void) const
Definition pointcloud.h:167
virtual bool Set_Field_Type(int Field, TSG_Data_Type Type)
virtual sLong Del_Selection(void)
virtual bool _Stats_Update(int Field) const
virtual bool Select(sLong Index, bool bInvert=false)
bool Create(void)
double Get_Y(void) const
Definition pointcloud.h:168
bool Save(const CSG_String &File, ESG_CRS_Format Format=ESG_CRS_Format::WKT) const
bool Create(const CSG_Projection &Projection)
bool Load(const CSG_String &File)
bool Contains(double x, double y) const
TSG_Intersection Intersects(const CSG_Rect &Rect) const
virtual TSG_Point Get_Point(int iPoint=0) const =0
virtual int Set_Point(double x, double y, int iPoint=0, int iPart=0)=0
virtual double Get_Z(int iPoint=0, int iPart=0, bool bAscending=true) const
Definition shapes.h:198
virtual const CSG_Rect & Get_Extent(void)
Definition shapes.h:818
CSG_Shapes(void)
Definition shapes.cpp:156
virtual CSG_Shape * Get_Shape(const CSG_Point &Point, double Epsilon=0.)
Definition shapes.cpp:483
double m_ZMax
Definition shapes.h:856
TSG_Shape_Type m_Type
Definition shapes.h:858
double m_ZMin
Definition shapes.h:856
TSG_Vertex_Type m_Vertex_Type
Definition shapes.h:860
friend class CSG_Shape
Definition shapes.h:781
CSG_Rect m_Extent_Selected
Definition shapes.h:862
int is_Evaluated(void) const
Definition mat_tools.h:741
static CSG_String Format(const char *Format,...)
const SG_Char * c_str(void) const
int Printf(const char *Format,...)
bool is_Empty(void) const
TSG_Data_Type m_Type
Definition table.h:490
void Set_Modified(bool bOn=true)
sLong m_Index
Definition table.h:266
bool Set_Value(int Field, const CSG_String &Value)
bool is_Modified(void) const
Definition table.h:255
void Set_Selected(bool bOn=true)
sLong asLong(int Field) const
uLong asULong(int Field) const
double asDouble(int Field) const
class CSG_Table * Get_Table(void)
Definition table.h:135
const SG_Char * asString(int Field, int Decimals=-99) const
const SG_Char * Get_Field_Name(int Field) const
Definition table.h:372
virtual bool _Stats_Update(int Field) const
Definition table.cpp:1229
sLong Get_Count(void) const
Definition table.h:410
bool _Set_Selection(sLong Index, sLong Selected)
double Get_Minimum(int Field) const
Definition table.h:391
sLong m_nRecords
Definition table.h:505
bool _Stats_Invalidate(void) const
Definition table.cpp:1205
virtual bool Select(sLong Index, bool bInvert=false)
CSG_Field_Info ** m_Field_Info
Definition table.h:501
friend class CSG_Table_Record
Definition table.h:296
CSG_Array m_Selection
Definition table.h:507
int Get_Field_Count(void) const
Definition table.h:371
bool _Add_Selection(sLong Index)
sLong m_nBuffer
Definition table.h:505
int m_nFields
Definition table.h:503
CSG_Rect m_Extent
Definition table.h:509
sLong Get_Selection_Index(sLong Index=0) const
Definition table.h:445
sLong Get_Selection_Count(void) const
Definition table.h:444
bool Del_Index(void)
Definition table.cpp:1396
bool _Del_Selection(sLong Index)
TSG_Data_Type Get_Field_Type(int Field) const
Definition table.h:373
double Get_Maximum(int Field) const
Definition table.h:392
double SG_Get_Distance(double ax, double ay, double bx, double by, bool bPolar)
struct SSG_Point TSG_Point
struct SSG_Point_3D TSG_Point_3D
@ INTERSECTION_None
Definition geo_tools.h:102
struct SSG_Rect TSG_Rect
#define PC_SIZE_TYPE(type)
#define PC_SIZE_STRING
CSG_PointCloud * SG_Create_PointCloud(void)
#define PC_FILE_VERSION
#define PC_SIZE_FIELD(field)
@ POINTCLOUD_FILE_FORMAT_Compressed
Definition pointcloud.h:92
@ POINTCLOUD_FILE_FORMAT_Undefined
Definition pointcloud.h:90
@ POINTCLOUD_FILE_FORMAT_Normal
Definition pointcloud.h:91
@ SG_VERTEX_TYPE_XYZ
Definition shapes.h:93
TSG_ADD_Shape_Copy_Mode
Definition shapes.h:124
@ SHAPE_COPY
Definition shapes.h:128
@ SHAPE_COPY_ATTR
Definition shapes.h:127
@ SHAPE_TYPE_Point
Definition shapes.h:102
double x
Definition geo_tools.h:129
double y
Definition geo_tools.h:129
double xMin
Definition geo_tools.h:468
double xMax
Definition geo_tools.h:468
double yMin
Definition geo_tools.h:468
double yMax
Definition geo_tools.h:468
#define SG_TABLE_REC_FLAG_Selected
Definition table.h:119