File: lwcompound.c

package info (click to toggle)
postgis 2.1.4%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 35,424 kB
  • ctags: 8,886
  • sloc: sql: 113,491; ansic: 97,254; xml: 41,127; sh: 11,925; java: 5,662; perl: 3,113; makefile: 2,265; python: 1,198; yacc: 438; lex: 114
file content (193 lines) | stat: -rw-r--r-- 4,726 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/**********************************************************************
 *
 * PostGIS - Spatial Types for PostgreSQL
 * http://postgis.refractions.net
 *
 * Copyright (C) 2001-2006 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU General Public Licence. See the COPYING file.
 *
 **********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "liblwgeom_internal.h"
#include "lwgeom_log.h"



int
lwcompound_is_closed(const LWCOMPOUND *compound)
{
	size_t size;
	int npoints=0;

	if ( lwgeom_has_z((LWGEOM*)compound) )
	{
		size = sizeof(POINT3D);
	}
	else
	{
		size = sizeof(POINT2D);
	}

	if ( compound->geoms[compound->ngeoms - 1]->type == CIRCSTRINGTYPE )
	{
		npoints = ((LWCIRCSTRING *)compound->geoms[compound->ngeoms - 1])->points->npoints;
	}
	else if (compound->geoms[compound->ngeoms - 1]->type == LINETYPE)
	{
		npoints = ((LWLINE *)compound->geoms[compound->ngeoms - 1])->points->npoints;
	}

	if ( memcmp(getPoint_internal( (POINTARRAY *)compound->geoms[0]->data, 0),
	            getPoint_internal( (POINTARRAY *)compound->geoms[compound->ngeoms - 1]->data,
	                               npoints - 1),
	            size) ) 
	{
		return LW_FALSE;
	}

	return LW_TRUE;
}

double lwcompound_length(const LWCOMPOUND *comp)
{
	double length = 0.0;
	LWLINE *line;
	if ( lwgeom_is_empty((LWGEOM*)comp) )
		return 0.0;
	line = lwcompound_segmentize(comp, 32);
	length = lwline_length(line);
	lwline_free(line);
	return length;
}

double lwcompound_length_2d(const LWCOMPOUND *comp)
{
	double length = 0.0;
	LWLINE *line;
	if ( lwgeom_is_empty((LWGEOM*)comp) )
		return 0.0;
	line = lwcompound_segmentize(comp, 32);
	length = lwline_length_2d(line);
	lwline_free(line);
	return length;
}

int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom)
{
	LWCOLLECTION *col = (LWCOLLECTION*)comp;
	
	/* Empty things can't continuously join up with other things */
	if ( lwgeom_is_empty(geom) )
	{
		LWDEBUG(4, "Got an empty component for a compound curve!");
		return LW_FAILURE;
	}
	
	if( col->ngeoms > 0 )
	{
		POINT4D last, first;
		/* First point of the component we are adding */
		LWLINE *newline = (LWLINE*)geom;
		/* Last point of the previous component */
		LWLINE *prevline = (LWLINE*)(col->geoms[col->ngeoms-1]);

		getPoint4d_p(newline->points, 0, &first);
		getPoint4d_p(prevline->points, prevline->points->npoints-1, &last);
		
		if ( !(FP_EQUALS(first.x,last.x) && FP_EQUALS(first.y,last.y)) )
		{
			LWDEBUG(4, "Components don't join up end-to-end!");
			LWDEBUGF(4, "first pt (%g %g %g %g) last pt (%g %g %g %g)", first.x, first.y, first.z, first.m, last.x, last.y, last.z, last.m);			
			return LW_FAILURE;
		}
	}
	
	col = lwcollection_add_lwgeom(col, geom);
	return LW_SUCCESS;
}

LWCOMPOUND *
lwcompound_construct_empty(int srid, char hasz, char hasm)
{
        LWCOMPOUND *ret = (LWCOMPOUND*)lwcollection_construct_empty(COMPOUNDTYPE, srid, hasz, hasm);
        return ret;
}

int lwgeom_contains_point(const LWGEOM *geom, const POINT2D *pt)
{
	switch( geom->type )
	{
		case LINETYPE:
			return ptarray_contains_point(((LWLINE*)geom)->points, pt);
		case CIRCSTRINGTYPE:
			return ptarrayarc_contains_point(((LWCIRCSTRING*)geom)->points, pt);
		case COMPOUNDTYPE:
			return lwcompound_contains_point((LWCOMPOUND*)geom, pt);
	}
	lwerror("lwgeom_contains_point failed");
	return LW_FAILURE;
}

int 
lwcompound_contains_point(const LWCOMPOUND *comp, const POINT2D *pt)
{
	int i;
	LWLINE *lwline;
	LWCIRCSTRING *lwcirc;
	int wn = 0;
	int winding_number = 0;
	int result;

	for ( i = 0; i < comp->ngeoms; i++ )
	{
		LWGEOM *lwgeom = comp->geoms[i];
		if ( lwgeom->type == LINETYPE )
		{
			lwline = lwgeom_as_lwline(lwgeom);
			if ( comp->ngeoms == 1 )
			{
				return ptarray_contains_point(lwline->points, pt); 
			}
			else
			{
				/* Don't check closure while doing p-i-p test */
				result = ptarray_contains_point_partial(lwline->points, pt, LW_FALSE, &winding_number);
			}
		}
		else
		{
			lwcirc = lwgeom_as_lwcircstring(lwgeom);
			if ( ! lwcirc ) {
				lwerror("Unexpected component of type %s in compound curve", lwtype_name(lwgeom->type));
				return 0;
			}
			if ( comp->ngeoms == 1 )
			{
				return ptarrayarc_contains_point(lwcirc->points, pt); 				
			}
			else
			{
				/* Don't check closure while doing p-i-p test */
				result = ptarrayarc_contains_point_partial(lwcirc->points, pt, LW_FALSE, &winding_number);
			}
		}

		/* Propogate boundary condition */
		if ( result == LW_BOUNDARY ) 
			return LW_BOUNDARY;

		wn += winding_number;
	}

	/* Outside */
	if (wn == 0)
		return LW_OUTSIDE;
	
	/* Inside */
	return LW_INSIDE;
}