SAGA API Version 9.14
Loading...
Searching...
No Matches
map_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// map_pointcloud.cpp //
15// //
16// Copyright (C) 2026 by //
17// Olaf Conrad //
18// //
19//-------------------------------------------------------//
20// //
21// This file is part of 'SAGA - System for Automated //
22// Geoscientific Analyses'. SAGA is free software; you //
23// can redistribute it and/or modify it under the terms //
24// of the GNU General Public License as published by the //
25// Free Software Foundation, either version 2 of the //
26// License, or (at your option) any later version. //
27// //
28// SAGA is distributed in the hope that it will be //
29// useful, but WITHOUT ANY WARRANTY; without even the //
30// implied warranty of MERCHANTABILITY or FITNESS FOR A //
31// PARTICULAR PURPOSE. See the GNU General Public //
32// License for more details. //
33// //
34// You should have received a copy of the GNU General //
35// Public License along with this program; if not, see //
36// <http://www.gnu.org/licenses/>. //
37// //
38//-------------------------------------------------------//
39// //
40// e-mail: oconrad@saga-gis.org //
41// //
42// contact: Olaf Conrad //
43// Institute of Geography //
44// University of Hamburg //
45// Germany //
46// //
48
49//---------------------------------------------------------
50#include "map_symbology.h"
51
52#include "map_layer.h"
53
54
56// //
57// //
58// //
60
61//---------------------------------------------------------
69
70
72// //
74
75//---------------------------------------------------------
77{
79
80 //-----------------------------------------------------
81 // Values...
82
83 Parameters.Add_Choice("NODE_VALUES", "AGGREGATION", _TL("Aggregation"), _TL(""), CSG_String::Format("%s|%s|%s|%s",
84 _TL("first" ),
85 _TL("last" ),
86 _TL("lowest" ),
87 _TL("highest")), 3
88 );
89
90 //-----------------------------------------------------
91 // Display...
92
93 Parameters.Add_Int("NODE_DISPLAY",
94 "DISPLAY_SIZE" , _TL("Point Size"),
95 _TL("Point radius size as number of pixels."),
96 1, 1, true, 10, true
97 );
98
99 //-----------------------------------------------------
100 // Colors...
101
102 Parameters.Add_Node ("NODE_COLORS", "NODE_RGB" , _TL("RGB" ), _TL(""));
103 Parameters.Add_Choice("NODE_RGB" , "RGB_FIELD", _TL("Field"), _TL(""), CSG_String::Format("<%s>", _TL("not set")));
104
105 //-----------------------------------------------------
106 // LUT
107
108 CSG_Table &LUT = *m_Parameters["CLASSIFIED_LUT"].asTable(); LUT.Del_Records();
109
112
113 #define ADD_CLASS(color, name, value) { CSG_Table_Record &r = *LUT.Add_Record(); r.Set_Value(0, color); r.Set_Value(1, name); r.Set_Value(3, value); r.Set_Value(4, value); }
114
115 ADD_CLASS(12632256, "Created, Never Classified" , 0);
116 ADD_CLASS( 8421504, "Unclassified" , 1);
117 ADD_CLASS( 4227327, "Ground" , 2);
118 ADD_CLASS( 65408, "Low Vegetation" , 3);
119 ADD_CLASS( 54528, "Medium Vegetation" , 4);
120 ADD_CLASS( 32768, "High Vegetation" , 5);
121 ADD_CLASS( 255, "Building" , 6);
122 ADD_CLASS( 16512, "Low Point (Noise)" , 7);
123 ADD_CLASS(16711808, "Model Key-Point (Mass Point)", 8);
124 ADD_CLASS(16711680, "Water" , 9);
125 ADD_CLASS(16711935, "Overlap Points" , 12);
126
127 //-----------------------------------------------------
128 if( m_pObject )
129 {
130 DataObject_Changed(); // update attribute choice lists
131
132 m_Parameters["STRETCH_FIELD"].Set_Value(2); // z attribute
133
135 }
136
137 return( true );
138}
139
140
142// //
144
145//---------------------------------------------------------
147{
148 if( Flags & PARAMETER_CHECK_VALUES )
149 {
150 // nop
151 }
152
153 //-----------------------------------------------------
154 if( Flags & PARAMETER_CHECK_ENABLE )
155 {
156 // nop
157 }
158
159 //-----------------------------------------------------
160 return( CSG_Map_Layer::Parameter_Changed(Parameters, Parameter, Flags) );
161}
162
163
165// //
167
168//---------------------------------------------------------
170{
172
173 //-----------------------------------------------------
174 Set_Fields_Choice(m_Parameters["CLASSIFIED_FIELD" ], false, false);
175 Set_Fields_Choice(m_Parameters["CLASSIFIED_NORMALIZE" ], true, true);
176 Set_Fields_Choice(m_Parameters["STRETCH_FIELD" ], true, false);
177 Set_Fields_Choice(m_Parameters["STRETCH_NORMALIZE"], true, true);
178 Set_Fields_Choice(m_Parameters["RGB_FIELD" ], true, false);
179
180 //-----------------------------------------------------
181 return( true );
182}
183
184//---------------------------------------------------------
186{
188
189 //-----------------------------------------------------
190 switch( m_Parameters["COLOR_SYMBOLS"].asInt() )
191 {
192 default: // CSG_Map_Symbology::SINGLE
193 m_Stretch.Value = -1;
194 break;
195
196 case 1: // CSG_Map_Symbology::CLASSIFIED
197 m_Stretch.Value = Get_Fields_Choice(m_Parameters["CLASSIFIED_FIELD" ]);
198 m_Stretch.Normal = Get_Fields_Choice(m_Parameters["CLASSIFIED_NORMALIZE"]);
199 m_Stretch.Scale = 1.;
200 break;
201
202 case 2: // CSG_Map_Symbology::DISCRETE
203 case 3: // CSG_Map_Symbology::GRADUATED
204 m_Stretch.Value = Get_Fields_Choice(m_Parameters["STRETCH_FIELD" ]);
205 m_Stretch.Normal = Get_Fields_Choice(m_Parameters["STRETCH_NORMALIZE"]);
206 m_Stretch.Scale = m_Parameters("STRETCH_NORMALIZE_FORMAT")->asInt() == 0 ? 1. : 100.;
207 break;
208
209 case 4: // CSG_Map_Symbology::RGB
210 m_Stretch.Value = Get_Fields_Choice(m_Parameters["RGB_FIELD"]);
211 m_Stretch.Normal = -1; m_pSymbology->Set_Mode(CSG_Map_Symbology::RGB);
212 break;
213 }
214
215 if( m_Stretch.Value < 0 )
216 {
218 }
219
220 //-----------------------------------------------------
221 long Color = m_Parameters["SINGLE_COLOR"].asColor();
222 m_Color_Pen = wxColour(SG_GET_R(Color), SG_GET_G(Color), SG_GET_B(Color));
223
224 m_PointSize = m_Parameters["DISPLAY_SIZE"].asInt() - 1;
225
226 //-----------------------------------------------------
227 return( true );
228}
229
230
232// //
234
235//---------------------------------------------------------
237{
238 return( false );
239}
240
241
243// //
245
246//---------------------------------------------------------
248{
249 if( m_pObject == NULL || Get_Extent().Intersects(dc_Map.rWorld()) == INTERSECTION_None )
250 {
251 return;
252 }
253
254 //-----------------------------------------------------
255 if( (Flags & LAYER_DRAW_FLAG_THUMBNAIL) != 0 )
256 {
257 _Draw_Thumbnail(dc_Map);
258
259 return;
260 }
261
262 //-----------------------------------------------------
263 if( dc_Map.Draw_Image_Begin(m_Parameters("TRANSPARENCY")->asDouble() / 100.) )
264 {
265 _Draw_Points(dc_Map, (Flags & LAYER_DRAW_FLAG_NOEDITS) != 0);
266
267 dc_Map.Draw_Image_End();
268 }
269}
270
271
273// //
275
276//---------------------------------------------------------
277inline void CSG_Map_PointCloud::_Draw_Pixel(CSG_Map_DC &dc_Map, int x, int y, double z, int Color)
278{
279 if( !m_Z.is_Valid() ) // if( m_Aggregation == 1 ) // last value
280 {
281 dc_Map.Draw_Image_Pixel(x, y, Color);
282 }
283 else if( m_Z.is_InGrid(x, y) )
284 {
285 switch( m_Aggregation )
286 {
287 case 0: // first value
288 if( m_N.asInt(x, y) == 0 )
289 {
290 dc_Map.Draw_Image_Pixel(x, y, Color);
291 }
292 break;
293
294 case 2: // lowest z
295 if( m_N.asInt(x, y) == 0 || z < m_Z.asDouble(x, y) )
296 {
297 dc_Map.Draw_Image_Pixel(x, y, Color); m_Z.Set_Value(x, y, z);
298 }
299 break;
300
301 case 3: // highest z
302 if( m_N.asInt(x, y) == 0 || z > m_Z.asDouble(x, y) )
303 {
304 dc_Map.Draw_Image_Pixel(x, y, Color); m_Z.Set_Value(x, y, z);
305 }
306 break;
307 }
308
309 m_N.Add_Value(x, y, 1);
310 }
311}
312
313//---------------------------------------------------------
314void CSG_Map_PointCloud::_Draw_Symbol(CSG_Map_DC &dc_Map, const CSG_Point_3D &Point, int Color)
315{
316 int x = (int)dc_Map.xWorld2DC(Point.x) - m_Symbol.Get_NX() / 2;
317 int y = (int)dc_Map.yWorld2DC(Point.y) - m_Symbol.Get_NY() / 2;
318
319 for(int iy=0; iy<m_Symbol.Get_NY(); iy++) for(int ix=0; ix<m_Symbol.Get_NX(); ix++)
320 {
321 if( m_Symbol.asByte(ix, iy) )
322 {
323 _Draw_Pixel(dc_Map, x + ix, y + iy, Point.z, Color);
324 }
325 }
326}
327
328
330// //
332
333//---------------------------------------------------------
334void CSG_Map_PointCloud::_Draw_Points(CSG_Map_DC &dc_Map, bool bSkipSelection)
335{
336 m_Aggregation = m_Parameters("AGGREGATION")->asInt();
337
338 if( m_Aggregation != 1 )
339 {
340 m_Z.Create(SG_DATATYPE_Double, dc_Map.rDC().GetWidth(), dc_Map.rDC().GetHeight());
341 m_N.Create(SG_DATATYPE_Int , dc_Map.rDC().GetWidth(), dc_Map.rDC().GetHeight());
342 }
343
344 //-----------------------------------------------------
345 m_Symbol.Create(SG_DATATYPE_Byte, 1 + 2 * m_PointSize, 1 + 2 * m_PointSize);
346
347 for(int iy=0, dy=-m_PointSize; iy<m_Symbol.Get_NY(); iy++, dy++) for(int ix=0, dx=-m_PointSize; ix<m_Symbol.Get_NX(); ix++, dx++)
348 {
349 m_Symbol.Set_Value(ix, iy, sqrt(dx*dx + dy*dy) <= m_PointSize ? 1 : 0);
350 }
351
352 //-----------------------------------------------------
353 CSG_PointCloud *pPoints = m_pObject->asPointCloud(); bool bNumeric = SG_Data_Type_is_Numeric(pPoints->Get_Field_Type(m_Stretch.Value));
354
355 #pragma omp parallel for
356 for(sLong i=0; i<pPoints->Get_Count(); i++)
357 {
358 if( bSkipSelection && pPoints->is_Selected(i) )
359 {
360 continue;
361 }
362
363 if( m_Stretch.Value >= 0 && (pPoints->is_NoData(i, m_Stretch.Value) || (m_Stretch.Normal >= 0 && (pPoints->is_NoData(i, m_Stretch.Normal) || !pPoints->Get_Value(i, m_Stretch.Normal)))) )
364 {
365 continue;
366 }
367
368 TSG_Point_3D Point = pPoints->Get_Point(i);
369
370 if( dc_Map.rWorld().Contains(Point.x, Point.y) == false )
371 {
372 continue;
373 }
374
375 //-----------------------------------------------------
376 // int x = (int)dc_Map.xWorld2DC(Point.x);
377 // int y = (int)dc_Map.yWorld2DC(Point.y);
378
379 if( m_pSymbology->Get_Mode() == CSG_Map_Symbology::CLASSIFIED && !bNumeric ) // string
380 {
381 int Color; CSG_String Value;
382
383 if( pPoints->Get_Value(i, m_Stretch.Value, Value) && m_pSymbology->Get_Class_Color_byValue(Value, Color) )
384 {
385 _Draw_Symbol(dc_Map, Point, Color);
386 }
387 }
388 else // number
389 {
390 int Color; double Value = pPoints->Get_Value(i, m_Stretch.Value); if( m_Stretch.Normal >= 0 ) { Value *= m_Stretch.Normal / pPoints->Get_Value(i, m_Stretch.Normal); }
391
392 if( m_pSymbology->Get_Class_Color_byValue(Value, Color) )
393 {
394 _Draw_Symbol(dc_Map, Point, Color);
395 }
396 }
397 }
398
399 //-----------------------------------------------------
400 m_Z.Destroy();
401 m_N.Destroy();
402}
403
404
406// //
408
409//---------------------------------------------------------
410void CSG_Map_PointCloud::_Draw_Thumbnail(CSG_Map_DC &dc_Map)
411{
412 if( dc_Map.Draw_Image_Begin(0.) )
413 {
414 CSG_PointCloud *pPoints = m_pObject->asPointCloud();
415
416 sLong n = 1 + (sLong)(pPoints->Get_Count() / (2 * dc_Map.rDC().GetWidth() * dc_Map.rDC().GetHeight()));
417
418 // #pragma omp parallel for
419 for(sLong i=0; i<pPoints->Get_Count(); i+=n)
420 {
421 if( m_Stretch.Value < 0 || (!pPoints->is_NoData(i, m_Stretch.Value) && (m_Stretch.Normal < 0 || (!pPoints->is_NoData(i, m_Stretch.Normal) && pPoints->Get_Value(i, m_Stretch.Normal) != 0.))) )
422 {
423 TSG_Point_3D Point = pPoints->Get_Point(i);
424
425 int x = (int)dc_Map.xWorld2DC(Point.x);
426 int y = (int)dc_Map.yWorld2DC(Point.y);
427
428 int Color; double Value = pPoints->Get_Value(i, m_Stretch.Value); if( m_Stretch.Normal >= 0 ) { Value *= m_Stretch.Scale / pPoints->Get_Value(i, m_Stretch.Normal); }
429
430 if( m_pSymbology->Get_Class_Color_byValue(Value, Color) )
431 {
432 dc_Map.Draw_Image_Pixel(x, y, Color);
433 }
434 }
435 }
436
437 dc_Map.Draw_Image_End();
438 }
439}
440
441
443// //
444// //
445// //
447
448//---------------------------------------------------------
bool SG_Data_Type_is_Numeric(TSG_Data_Type Type)
Definition api_core.cpp:199
#define SG_GET_B(rgb)
Definition api_core.h:1350
#define SG_GET_G(rgb)
Definition api_core.h:1349
signed long long sLong
Definition api_core.h:158
#define SG_GET_R(rgb)
Definition api_core.h:1348
@ SG_DATATYPE_Byte
Definition api_core.h:1045
@ SG_DATATYPE_Double
Definition api_core.h:1054
@ SG_DATATYPE_Int
Definition api_core.h:1050
@ SG_DATATYPE_String
Definition api_core.h:1055
#define _TL(s)
Definition api_core.h:1619
virtual bool is_Valid(void) const
Definition grid.cpp:441
bool Draw_Image_Begin(double Transparency, Mode Mode=Mode::Transparent)
Definition map_dc.cpp:374
double yWorld2DC(double y, bool bRound=true)
Definition map_dc.h:147
const CSG_Rect & rWorld(void) const
Definition map_dc.h:124
double xWorld2DC(double x, bool bRound=true)
Definition map_dc.h:140
const wxRect & rDC(void) const
Definition map_dc.h:129
void Draw_Image_Pixel(int x, int y, int Color)
Definition map_dc.h:186
bool Draw_Image_End(void)
Definition map_dc.cpp:418
virtual bool Parameters_Changed(void)
bool Set_Fields_Choice(CSG_Parameter &Choice, bool bNumeric, bool bAddNone, bool bSelectNone=false)
static int Get_Fields_Choice(CSG_Parameter &Choice)
virtual bool DataObject_Changed(void)
virtual bool Parameter_Changed(CSG_Parameters &Parameters, CSG_Parameter &Parameter, int Flags)
CSG_Data_Object * m_pObject
Definition map_layer.h:151
bool Set_Object(CSG_Data_Object *pObject)
CSG_Rect Get_Extent(void) const
CSG_Parameters m_Parameters
Definition map_layer.h:149
class CSG_Map_Symbology * m_pSymbology
Definition map_layer.h:153
virtual bool Add_Parameters(CSG_Parameters &Parameters)
CSG_Map_Layer(void)
Definition map_layer.h:90
virtual bool Parameters_Changed(void)
virtual bool Parameter_Changed(CSG_Parameters &Parameters, CSG_Parameter &Parameter, int Flags)
virtual bool DataObject_Changed(void)
virtual void On_Draw(CSG_Map_DC &dc_Map, int Flags)
virtual bool Add_Parameters(CSG_Parameters &Parameters)
CSG_Map_PointCloud(CSG_PointCloud *pPointCloud=NULL)
bool asImage(CSG_Grid *pImage)
CSG_Parameter * Add_Choice(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, const CSG_String &Items, int Default=0)
bool Create(const CSG_Parameters &Parameters)
CSG_Parameter * Add_Int(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Value=0, int Minimum=0, bool bMinimum=false, int Maximum=0, bool bMaximum=false)
CSG_Parameter * Add_Node(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, bool bCollapsed=false)
virtual bool is_NoData(int Field) const
Definition pointcloud.h:174
sLong Get_Point(const CSG_Point &Point, double Epsilon=0.)
virtual double Get_Value(int Field) const
Definition pointcloud.h:180
virtual bool is_Selected(sLong Index) const
bool Contains(double x, double y) const
static CSG_String Format(const char *Format,...)
sLong Get_Count(void) const
Definition table.h:410
virtual bool Del_Records(void)
Definition table.cpp:936
TSG_Data_Type Get_Field_Type(int Field) const
Definition table.h:373
virtual bool Set_Field_Type(int Field, TSG_Data_Type Type)
Definition table.cpp:610
@ SG_DATAOBJECT_TYPE_PointCloud
Definition dataobject.h:123
struct SSG_Point_3D TSG_Point_3D
@ INTERSECTION_None
Definition geo_tools.h:102
#define LAYER_DRAW_FLAG_THUMBNAIL
Definition map_layer.h:74
#define LAYER_DRAW_FLAG_NOEDITS
Definition map_layer.h:77
#define ADD_CLASS(color, name, value)
#define asDouble(i)
#define PARAMETER_CHECK_ENABLE
Definition parameters.h:191
#define PARAMETER_CHECK_VALUES
Definition parameters.h:190
#define PARAMETER_CHECK_ALL
Definition parameters.h:192