1 /**********************************************************
2 * Version $Id$
3 *********************************************************/
4
5 ///////////////////////////////////////////////////////////
6 // //
7 // SAGA //
8 // //
9 // System for Automated Geoscientific Analyses //
10 // //
11 // Application Programming Interface //
12 // //
13 // Library: SAGA_API //
14 // //
15 //-------------------------------------------------------//
16 // //
17 // shape_points.cpp //
18 // //
19 // Copyright (C) 2005 by Olaf Conrad //
20 // //
21 //-------------------------------------------------------//
22 // //
23 // This file is part of 'SAGA - System for Automated //
24 // Geoscientific Analyses'. //
25 // //
26 // This library is free software; you can redistribute //
27 // it and/or modify it under the terms of the GNU Lesser //
28 // General Public License as published by the Free //
29 // Software Foundation, either version 2.1 of the //
30 // License, or (at your option) any later version. //
31 // //
32 // This library is distributed in the hope that it will //
33 // be useful, but WITHOUT ANY WARRANTY; without even the //
34 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
35 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
36 // License for more details. //
37 // //
38 // You should have received a copy of the GNU Lesser //
39 // General Public License along with this program; if //
40 // not, see <http://www.gnu.org/licenses/>. //
41 // //
42 //-------------------------------------------------------//
43 // //
44 // contact: Olaf Conrad //
45 // Institute of Geography //
46 // University of Goettingen //
47 // Goldschmidtstr. 5 //
48 // 37077 Goettingen //
49 // Germany //
50 // //
51 // e-mail: oconrad@saga-gis.org //
52 // //
53 ///////////////////////////////////////////////////////////
54
55 //---------------------------------------------------------
56
57
58 ///////////////////////////////////////////////////////////
59 // //
60 // //
61 // //
62 ///////////////////////////////////////////////////////////
63
64 //---------------------------------------------------------
65 #include "shapes.h"
66
67
68 ///////////////////////////////////////////////////////////
69 // //
70 // //
71 // //
72 ///////////////////////////////////////////////////////////
73
74 //---------------------------------------------------------
CSG_Shape_Points(CSG_Shapes * pOwner,int Index)75 CSG_Shape_Points::CSG_Shape_Points(CSG_Shapes *pOwner, int Index)
76 : CSG_Shape(pOwner, Index)
77 {
78 m_pParts = NULL;
79 m_nParts = 0;
80
81 m_bUpdate = true;
82 }
83
84 //---------------------------------------------------------
~CSG_Shape_Points(void)85 CSG_Shape_Points::~CSG_Shape_Points(void)
86 {
87 Destroy();
88 }
89
90
91 ///////////////////////////////////////////////////////////
92 // //
93 // //
94 // //
95 ///////////////////////////////////////////////////////////
96
97 //---------------------------------------------------------
Destroy(void)98 void CSG_Shape_Points::Destroy(void)
99 {
100 CSG_Shape::Destroy();
101
102 Del_Parts();
103 }
104
105
106 ///////////////////////////////////////////////////////////
107 // //
108 // //
109 // //
110 ///////////////////////////////////////////////////////////
111
112 //---------------------------------------------------------
On_Assign(CSG_Shape * pShape)113 bool CSG_Shape_Points::On_Assign(CSG_Shape *pShape)
114 {
115 Del_Parts();
116
117 TSG_Vertex_Type Vertex_Type = Get_Vertex_Type();
118
119 if( pShape->Get_Type() == SHAPE_TYPE_Point ) // just in case...
120 {
121 Add_Point(pShape->Get_Point(0));
122
123 switch( Vertex_Type )
124 {
125 case SG_VERTEX_TYPE_XYZM: Get_Part(0)->Set_M(pShape->Get_M(0), 0);
126 case SG_VERTEX_TYPE_XYZ : Get_Part(0)->Set_Z(pShape->Get_Z(0), 0);
127 default: break;
128 }
129
130 return( true );
131 }
132
133 for(int iPart=0; iPart<pShape->Get_Part_Count(); iPart++)
134 {
135 Add_Part(((CSG_Shape_Points *)pShape)->Get_Part(iPart));
136 }
137
138 return( true );
139 }
140
141
142 ///////////////////////////////////////////////////////////
143 // //
144 // //
145 // //
146 ///////////////////////////////////////////////////////////
147
148 //---------------------------------------------------------
_Add_Part(void)149 int CSG_Shape_Points::_Add_Part(void)
150 {
151 m_pParts = (CSG_Shape_Part **)SG_Realloc(m_pParts , (m_nParts + 1) * sizeof(CSG_Shape_Part *));
152 m_pParts[m_nParts] = _Get_Part();
153
154 m_nParts++;
155
156 return( m_nParts );
157 }
158
159 //---------------------------------------------------------
Add_Part(CSG_Shape_Part * pPart)160 int CSG_Shape_Points::Add_Part(CSG_Shape_Part *pPart)
161 {
162 int iPart = m_nParts;
163
164 if( pPart && _Add_Part() > iPart )
165 {
166 m_pParts[iPart]->Assign(pPart);
167 }
168
169 return( m_nParts );
170 }
171
172 //---------------------------------------------------------
Del_Part(int del_Part)173 int CSG_Shape_Points::Del_Part(int del_Part)
174 {
175 if( del_Part >= 0 && del_Part < m_nParts )
176 {
177 delete(m_pParts[del_Part]);
178
179 m_nParts--;
180
181 for(int iPart=del_Part; iPart<m_nParts; iPart++)
182 {
183 m_pParts[iPart] = m_pParts[iPart + 1];
184 }
185
186 m_pParts = (CSG_Shape_Part **)SG_Realloc(m_pParts , m_nParts * sizeof(CSG_Shape_Part *));
187
188 _Invalidate();
189 }
190
191 return( m_nParts );
192 }
193
194 //---------------------------------------------------------
Del_Parts(void)195 int CSG_Shape_Points::Del_Parts(void)
196 {
197 for(int iPart=m_nParts-1; iPart>=0; iPart--)
198 {
199 Del_Part(iPart);
200 }
201
202 return( m_nParts );
203 }
204
205
206 ///////////////////////////////////////////////////////////
207 // //
208 // //
209 // //
210 ///////////////////////////////////////////////////////////
211
212 //---------------------------------------------------------
Add_Point(double x,double y,int iPart)213 int CSG_Shape_Points::Add_Point(double x, double y, int iPart)
214 {
215 if( iPart >= m_nParts )
216 {
217 for(int i=m_nParts; i<=iPart; i++)
218 {
219 _Add_Part();
220 }
221 }
222
223 return( iPart >= 0 && iPart < m_nParts ? m_pParts[iPart]->Add_Point(x, y) : 0 );
224 }
225
226 //---------------------------------------------------------
Ins_Point(double x,double y,int iPoint,int iPart)227 int CSG_Shape_Points::Ins_Point(double x, double y, int iPoint, int iPart)
228 {
229 if( iPart >= m_nParts )
230 {
231 for(int i=m_nParts; i<=iPart; i++)
232 {
233 _Add_Part();
234 }
235 }
236
237 return( iPart >= 0 && iPart < m_nParts ? m_pParts[iPart]->Ins_Point(x, y, iPoint) : 0 );
238 }
239
240 //---------------------------------------------------------
Set_Point(double x,double y,int iPoint,int iPart)241 int CSG_Shape_Points::Set_Point(double x, double y, int iPoint, int iPart)
242 {
243 return( iPart >= 0 && iPart < m_nParts ? m_pParts[iPart]->Set_Point(x, y, iPoint) : 0 );
244 }
245
246 //---------------------------------------------------------
Del_Point(int del_Point,int iPart)247 int CSG_Shape_Points::Del_Point(int del_Point, int iPart)
248 {
249 return( iPart >= 0 && iPart < m_nParts ? m_pParts[iPart]->Del_Point(del_Point) : 0 );
250 }
251
252 //---------------------------------------------------------
Get_Point(int iPoint)253 TSG_Point CSG_Shape_Points::Get_Point(int iPoint)
254 {
255 for(int iPart=0; iPart<m_nParts; iPoint-=m_pParts[iPart++]->Get_Count())
256 {
257 if( iPoint < m_pParts[iPart]->Get_Count() )
258 {
259 return( m_pParts[iPart]->Get_Point(iPoint) );
260 }
261 }
262
263 return( CSG_Point(0.0, 0.0) );
264 }
265
266
267 ///////////////////////////////////////////////////////////
268 // //
269 // //
270 // //
271 ///////////////////////////////////////////////////////////
272
273 //---------------------------------------------------------
_Update_Extent(void)274 void CSG_Shape_Points::_Update_Extent(void)
275 {
276 if( m_bUpdate )
277 {
278 bool bFirst;
279 int iPart;
280
281 for(iPart=0, bFirst=true, m_nPoints=0; iPart<m_nParts; iPart++)
282 {
283 CSG_Shape_Part *pPart = m_pParts[iPart];
284
285 if( pPart->Get_Count() > 0 )
286 {
287 m_nPoints += pPart->Get_Count();
288
289 if( bFirst )
290 {
291 bFirst = false;
292
293 m_Extent = pPart->Get_Extent();
294
295 m_ZMin = pPart->Get_ZMin();
296 m_ZMax = pPart->Get_ZMax();
297
298 m_MMin = pPart->Get_MMin();
299 m_MMax = pPart->Get_MMax();
300 }
301 else
302 {
303 m_Extent.Union(pPart->Get_Extent());
304
305 if( m_ZMin > pPart->Get_ZMin() ) m_ZMin = pPart->Get_ZMin();
306 if( m_ZMax < pPart->Get_ZMax() ) m_ZMax = pPart->Get_ZMax();
307
308 if( m_MMin > pPart->Get_MMin() ) m_MMin = pPart->Get_MMin();
309 if( m_MMax < pPart->Get_MMax() ) m_MMax = pPart->Get_MMax();
310 }
311 }
312 }
313
314 m_bUpdate = false;
315 }
316 }
317
318
319 ///////////////////////////////////////////////////////////
320 // //
321 // //
322 // //
323 ///////////////////////////////////////////////////////////
324
325 //---------------------------------------------------------
Get_Centroid(void)326 TSG_Point CSG_Shape_Points::Get_Centroid(void)
327 {
328 int n = 0;
329 CSG_Point c(0.0, 0.0);
330
331 for(int iPart=0; iPart<Get_Part_Count(); iPart++)
332 {
333 for(int iPoint=0; iPoint<Get_Point_Count(iPart); iPoint++)
334 {
335 c += Get_Point(iPoint, iPart);
336 n ++;
337 }
338 }
339
340 if( n > 0 )
341 {
342 c.Assign(c.Get_X() / n, c.Get_Y() / n);
343 }
344
345 return( c );
346 }
347
348
349 ///////////////////////////////////////////////////////////
350 // //
351 // //
352 // //
353 ///////////////////////////////////////////////////////////
354
355 //---------------------------------------------------------
Get_Distance(TSG_Point Point)356 double CSG_Shape_Points::Get_Distance(TSG_Point Point)
357 {
358 TSG_Point Next;
359
360 return( Get_Distance(Point, Next) );
361 }
362
363 //---------------------------------------------------------
Get_Distance(TSG_Point Point,TSG_Point & Next)364 double CSG_Shape_Points::Get_Distance(TSG_Point Point, TSG_Point &Next)
365 {
366 int iPart;
367 double d, Distance;
368 TSG_Point pt;
369
370 Distance = Get_Distance(Point, Next, 0);
371
372 for(iPart=1; iPart<m_nParts && Distance!=0.0; iPart++)
373 {
374 if( (d = Get_Distance(Point, pt, iPart)) >= 0.0
375 && (d < Distance || Distance < 0.0) )
376 {
377 Distance = d;
378 Next = pt;
379 }
380 }
381
382 return( Distance );
383 }
384
385 //---------------------------------------------------------
Get_Distance(TSG_Point Point,int iPart)386 double CSG_Shape_Points::Get_Distance(TSG_Point Point, int iPart)
387 {
388 TSG_Point Next;
389
390 return( Get_Distance(Point, Next, iPart) );
391 }
392
393 //---------------------------------------------------------
Get_Distance(TSG_Point Point,TSG_Point & Next,int iPart)394 double CSG_Shape_Points::Get_Distance(TSG_Point Point, TSG_Point &Next, int iPart)
395 {
396 int i;
397 double d, Distance;
398 TSG_Point *pA;
399
400 Distance = -1.0;
401
402 if( iPart >= 0 && iPart < m_nParts )
403 {
404 for(i=0, pA=m_pParts[iPart]->m_Points; i<m_pParts[iPart]->Get_Count() && Distance!=0.0; i++, pA++)
405 {
406 if( (d = SG_Get_Distance(Point, *pA)) < Distance || Distance < 0.0 )
407 {
408 Distance = d;
409 Next = *pA;
410 }
411 }
412 }
413
414 return( Distance );
415 }
416
417
418 ///////////////////////////////////////////////////////////
419 // //
420 // //
421 // //
422 ///////////////////////////////////////////////////////////
423
424 //---------------------------------------------------------
On_Intersects(CSG_Shape * pShape)425 TSG_Intersection CSG_Shape_Points::On_Intersects(CSG_Shape *pShape)
426 {
427 CSG_Shape *piPoints, *pjPoints;
428
429 if( Get_Point_Count() < pShape->Get_Point_Count() )
430 {
431 piPoints = this;
432 pjPoints = pShape;
433 }
434 else
435 {
436 piPoints = pShape;
437 pjPoints = this;
438 }
439
440 bool bIn = false;
441 bool bOut = false;
442
443 for(int iPart=0; iPart<piPoints->Get_Part_Count(); iPart++)
444 {
445 for(int iPoint=0; iPoint<piPoints->Get_Point_Count(iPart); iPoint++)
446 {
447 CSG_Point Point = piPoints->Get_Point(iPoint, iPart);
448
449 for(int jPart=0; jPart<pjPoints->Get_Part_Count(); jPart++)
450 {
451 for(int jPoint=0; jPoint<pjPoints->Get_Point_Count(jPart); jPoint++)
452 {
453 if( Point.is_Equal(pjPoints->Get_Point(jPoint, jPart)) )
454 {
455 bIn = true;
456 }
457 else
458 {
459 bOut = true;
460 }
461
462 if( bIn && bOut )
463 {
464 return( INTERSECTION_Overlaps );
465 }
466 }
467 }
468 }
469 }
470
471 if( bIn )
472 {
473 return( piPoints == this ? INTERSECTION_Contained : INTERSECTION_Contains );
474 }
475
476 return( INTERSECTION_None );
477 }
478
479 //---------------------------------------------------------
On_Intersects(TSG_Rect Extent)480 TSG_Intersection CSG_Shape_Points::On_Intersects(TSG_Rect Extent)
481 {
482 for(int iPart=0; iPart<m_nParts; iPart++)
483 {
484 TSG_Point *p = m_pParts[iPart]->m_Points;
485
486 for(int iPoint=0; iPoint<m_pParts[iPart]->Get_Count(); iPoint++, p++)
487 {
488 if( Extent.xMin <= p->x && p->x <= Extent.xMax
489 && Extent.yMin <= p->y && p->y <= Extent.yMax )
490 {
491 return( INTERSECTION_Overlaps );
492 }
493 }
494 }
495
496 return( INTERSECTION_None );
497 }
498
499
500 ///////////////////////////////////////////////////////////
501 // //
502 // //
503 // //
504 ///////////////////////////////////////////////////////////
505
506 //---------------------------------------------------------
507