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