From fc8064f2041384b1f9312c85a64535955d7d48cd Mon Sep 17 00:00:00 2001
From: Paul Ramsey <pramsey@cleverelephant.ca>
Date: Fri, 6 Mar 2015 14:45:37 +0000
Subject: [PATCH] #3074, first piece of infrastructure, count points in a piece

git-svn-id: http://svn.osgeo.org/postgis/trunk@13322 b70326c6-7e19-0410-871a-916f4a2858ee
---
 liblwgeom/cunit/cu_misc.c      | 19 ++++++++++++
 liblwgeom/g_box.c              | 11 +++++++
 liblwgeom/liblwgeom_internal.h |  4 +++
 liblwgeom/lwgeom.c             | 54 ++++++++++++++++++++++++++++++++++
 liblwgeom/ptarray.c            | 16 ++++++++++
 5 files changed, 104 insertions(+)

diff --git a/liblwgeom/cunit/cu_misc.c b/liblwgeom/cunit/cu_misc.c
index 24a8a1900..3deeba506 100644
--- a/liblwgeom/cunit/cu_misc.c
+++ b/liblwgeom/cunit/cu_misc.c
@@ -139,6 +139,24 @@ static void test_grid(void)
 	lwgeom_free(geomgrid);		
 }
 
+static void test_rect_count(void)
+{
+	GBOX box;
+	int n;
+	static char *wkt = "MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))";
+	LWGEOM *geom = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_ALL);
+
+	box.xmin = -5;  box.ymin = -5;
+	box.xmax =  5;  box.ymax =  5;
+	n = lwgeom_npoints_in_rect(geom, &box);
+	CU_ASSERT_EQUAL(2, n);
+
+	box.xmin = -5;  box.ymin = -5;
+	box.xmax = 15;  box.ymax = 15; 
+	n = lwgeom_npoints_in_rect(geom, &box);
+	CU_ASSERT_EQUAL(5, n);
+}
+
 
 /*
 ** Used by the test harness to register the tests in this file.
@@ -153,4 +171,5 @@ void misc_suite_setup(void)
 	PG_ADD_TEST(suite, test_misc_area);
 	PG_ADD_TEST(suite, test_misc_wkb);
 	PG_ADD_TEST(suite, test_grid);
+	PG_ADD_TEST(suite, test_rect_count);
 }
diff --git a/liblwgeom/g_box.c b/liblwgeom/g_box.c
index 8604545c9..43ae3fcc8 100644
--- a/liblwgeom/g_box.c
+++ b/liblwgeom/g_box.c
@@ -307,6 +307,17 @@ gbox_contains_2d(const GBOX *g1, const GBOX *g2)
 	return LW_TRUE;
 }
 
+int 
+gbox_contains_point2d(const GBOX *g, const POINT2D *p)
+{
+	if ( ( g->xmin <= p->x ) && ( g->xmax >= p->x ) &&
+	     ( g->ymin <= p->y ) && ( g->ymax >= p->y ) )
+	{
+		return LW_TRUE;
+	}
+	return LW_FALSE;
+}
+
 /**
 * Warning, this function is only good for x/y/z boxes, used
 * in unit testing of geodetic box generation.
diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h
index ab9fc446d..9495d4a34 100644
--- a/liblwgeom/liblwgeom_internal.h
+++ b/liblwgeom/liblwgeom_internal.h
@@ -435,3 +435,7 @@ extern int _lwgeom_interrupt_requested;
 }
 
 #endif /* _LIBLWGEOM_INTERNAL_H */
+
+int ptarray_npoints_in_rect(const POINTARRAY *pa, const GBOX *gbox);
+int gbox_contains_point2d(const GBOX *g, const POINT2D *p);
+int lwgeom_npoints_in_rect(const LWGEOM *geom, const GBOX *gbox);
diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index 829b3c7e8..186e8283c 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -1818,3 +1818,57 @@ lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
 			return NULL;
 	}
 }
+
+
+int
+lwgeom_npoints_in_rect(const LWGEOM *geom, const GBOX *gbox)
+{
+	const GBOX *geombox = lwgeom_get_bbox(geom);
+	
+	if ( ! gbox_overlaps_2d(geombox, gbox) )
+		return 0;
+	
+	switch ( geom->type )
+	{
+		case POINTTYPE:
+			return ptarray_npoints_in_rect(((LWPOINT*)geom)->point, gbox);
+
+		case CIRCSTRINGTYPE:
+		case LINETYPE:
+			return ptarray_npoints_in_rect(((LWLINE*)geom)->points, gbox);
+
+		case POLYGONTYPE:
+		{
+			int i, n = 0;
+			LWPOLY *poly = (LWPOLY*)geom;
+			for ( i = 0; i < poly->nrings; i++ )
+			{
+				n += ptarray_npoints_in_rect(poly->rings[i], gbox);
+			}
+			return n;
+		}
+
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case COMPOUNDTYPE:
+		case COLLECTIONTYPE:
+		{
+			int i, n = 0;
+			LWCOLLECTION *col = (LWCOLLECTION*)geom;
+			for ( i = 0; i < col->ngeoms; i++ )
+			{
+				n += lwgeom_npoints_in_rect(col->geoms[i], gbox);
+			}
+			return n;
+		}
+		default:
+		{
+			lwerror("lwgeom_npoints_in_rect: Unsupported geometry type: %s",
+			        lwtype_name(geom->type));
+			return 0;
+		}
+	}
+	return 0;
+}
+
diff --git a/liblwgeom/ptarray.c b/liblwgeom/ptarray.c
index 44a7f1ab5..5da8e6acd 100644
--- a/liblwgeom/ptarray.c
+++ b/liblwgeom/ptarray.c
@@ -1818,3 +1818,19 @@ ptarray_grid(const POINTARRAY *pa, const gridspec *grid)
 	return dpa;
 }
 
+int 
+ptarray_npoints_in_rect(const POINTARRAY *pa, const GBOX *gbox)
+{
+	const POINT2D *pt;
+	int n = 0;
+	int i;
+	for ( i = 0; i < pa->npoints; i++ )
+	{
+		pt = getPoint2d_cp(pa, i);
+		if ( gbox_contains_point2d(gbox, pt) )
+			n++;
+	}
+	return n;
+}
+
+
-- 
2.40.0