2 gpclib: General Polygon Clipping library for R
3 Copyright (C) 2003 Roger D. Peng <rpeng@jhsph.edu>
7 #include <Rinternals.h>
10 static int compute_polygon_size(gpc_polygon
*p
);
11 static void gpc_polygon_to_double(double *a
, int na
, gpc_polygon
*p
);
12 static void double_to_gpc_polygon(gpc_polygon
*p
, double *a
, int na
);
16 SEXP
Rgpc_polygon_clip(SEXP subjpoly
, SEXP clippoly
, SEXP op
) {
17 gpc_polygon subject
, clip
, result
;
18 int polysize
, nsubj
, nclip
, iop
;
20 double *xsubjpoly
, *xclippoly
, *xreturnval
;
22 PROTECT(subjpoly
= coerceVector(subjpoly
, REALSXP
));
23 PROTECT(clippoly
= coerceVector(clippoly
, REALSXP
));
24 PROTECT(op
= coerceVector(op
, INTSXP
));
26 nsubj
= length(subjpoly
);
27 nclip
= length(clippoly
);
28 xsubjpoly
= REAL(subjpoly
);
29 xclippoly
= REAL(clippoly
);
32 double_to_gpc_polygon(&subject
, xsubjpoly
, nsubj
);
33 double_to_gpc_polygon(&clip
, xclippoly
, nclip
);
36 gpc_polygon_clip(GPC_INT
, &subject
, &clip
, &result
);
38 gpc_polygon_clip(GPC_DIFF
, &subject
, &clip
, &result
);
40 gpc_polygon_clip(GPC_UNION
, &subject
, &clip
, &result
);
42 polysize
= compute_polygon_size(&result
);
44 PROTECT(returnval
= allocVector(REALSXP
, polysize
));
45 xreturnval
= REAL(returnval
);
47 gpc_polygon_to_double(xreturnval
, polysize
, &result
);
50 gpc_free_polygon(&subject);
51 gpc_free_polygon(&clip);
53 gpc_free_polygon(&result
);
63 /* unserialize the polygon */
65 static void double_to_gpc_polygon(gpc_polygon
*p
, double *a
, int na
)
69 p
->num_contours
= a
[0];
70 p
->hole
= (int *)R_alloc(p
->num_contours
, sizeof(int));
71 p
->contour
= (gpc_vertex_list
*)R_alloc(p
->num_contours
, sizeof(gpc_vertex_list
));
74 for(j
=0; j
< p
->num_contours
; j
++) {
75 p
->contour
[j
].num_vertices
= a
[i
++];
76 p
->contour
[j
].vertex
= (gpc_vertex
*)R_alloc(p
->contour
[j
].num_vertices
,
78 p
->hole
[j
] = (int) a
[i
++];
80 for(k
=0; k
< p
->contour
[j
].num_vertices
; k
++) {
81 p
->contour
[j
].vertex
[k
].x
= a
[i
++];
82 p
->contour
[j
].vertex
[k
].y
= a
[i
++];
85 Rprintf("index out of range: %d\n", i
);
91 /* serialize polygon to vector */
93 static void gpc_polygon_to_double(double *a
, int na
, gpc_polygon
*p
)
97 a
[0] = p
->num_contours
;
100 for(j
=0; j
< p
->num_contours
; j
++) {
101 a
[i
++] = p
->contour
[j
].num_vertices
;
102 a
[i
++] = (double) p
->hole
[j
];
105 Rprintf("index out of range: %d\n", i
);
108 for(k
=0; k
< p
->contour
[j
].num_vertices
; k
++) {
109 a
[i
++] = p
->contour
[j
].vertex
[k
].x
;
112 Rprintf("index out of range: %d\n", i
);
115 a
[i
++] = p
->contour
[j
].vertex
[k
].y
;
118 Rprintf("index out of range: %d\n", i
);
126 static int compute_polygon_size(gpc_polygon
*p
)
130 psize
+= p
->num_contours
;
131 psize
+= p
->num_contours
; /* for the hole flags */
133 for(i
=0; i
< p
->num_contours
; i
++) {
134 psize
+= 2 * p
->contour
[i
].num_vertices
;
167 Older code had separate functions for intersect/union/diff. These
168 are now done with a single function + flag (duh!). But I'll save these
169 functions just in case....
172 /*********************************************************************
174 SEXP gpc_polygon_intersect(SEXP subjpoly, SEXP clippoly)
176 gpc_polygon subject, clip, result;
177 int polysize, nsubj, nclip;
180 double *xsubjpoly, *xclippoly;
182 PROTECT(subjpoly = AS_NUMERIC(subjpoly));
183 PROTECT(clippoly = AS_NUMERIC(clippoly));
184 nsubj = LENGTH(subjpoly);
185 nclip = LENGTH(clippoly);
187 xsubjpoly = NUMERIC_POINTER(subjpoly);
188 xclippoly = NUMERIC_POINTER(clippoly);
190 double_to_gpc_polygon(&subject, xsubjpoly, nsubj);
191 double_to_gpc_polygon(&clip, xclippoly, nclip);
192 gpc_polygon_clip(GPC_INT, &subject, &clip, &result);
194 polysize = compute_polygon_size(&result);
196 PROTECT(returnval = NEW_NUMERIC(polysize));
197 xreturnval = NUMERIC_POINTER(returnval);
199 gpc_polygon_to_double(xreturnval, polysize, &result);
201 gpc_free_polygon(&subject);
202 gpc_free_polygon(&clip);
203 gpc_free_polygon(&result);
212 SEXP gpc_polygon_difference(SEXP subjpoly, SEXP clippoly)
214 gpc_polygon subject, clip, result;
215 int polysize, nsubj, nclip;
218 double *xsubjpoly, *xclippoly;
220 PROTECT(subjpoly = AS_NUMERIC(subjpoly));
221 PROTECT(clippoly = AS_NUMERIC(clippoly));
222 nsubj = LENGTH(subjpoly);
223 nclip = LENGTH(clippoly);
225 xsubjpoly = NUMERIC_POINTER(subjpoly);
226 xclippoly = NUMERIC_POINTER(clippoly);
228 double_to_gpc_polygon(&subject, xsubjpoly, nsubj);
229 double_to_gpc_polygon(&clip, xclippoly, nclip);
230 gpc_polygon_clip(GPC_DIFF, &subject, &clip, &result);
232 polysize = compute_polygon_size(&result);
234 PROTECT(returnval = NEW_NUMERIC(polysize));
235 xreturnval = NUMERIC_POINTER(returnval);
237 gpc_polygon_to_double(xreturnval, polysize, &result);
239 gpc_free_polygon(&subject);
240 gpc_free_polygon(&clip);
241 gpc_free_polygon(&result);
249 SEXP gpc_polygon_union(SEXP subjpoly, SEXP clippoly)
251 gpc_polygon subject, clip, result;
252 int polysize, nsubj, nclip;
255 double *xsubjpoly, *xclippoly;
257 PROTECT(subjpoly = AS_NUMERIC(subjpoly));
258 PROTECT(clippoly = AS_NUMERIC(clippoly));
259 nsubj = LENGTH(subjpoly);
260 nclip = LENGTH(clippoly);
262 xsubjpoly = NUMERIC_POINTER(subjpoly);
263 xclippoly = NUMERIC_POINTER(clippoly);
265 double_to_gpc_polygon(&subject, xsubjpoly, nsubj);
266 double_to_gpc_polygon(&clip, xclippoly, nclip);
267 gpc_polygon_clip(GPC_UNION, &subject, &clip, &result);
269 polysize = compute_polygon_size(&result);
271 PROTECT(returnval = NEW_NUMERIC(polysize));
272 xreturnval = NUMERIC_POINTER(returnval);
274 gpc_polygon_to_double(xreturnval, polysize, &result);
276 gpc_free_polygon(&subject);
277 gpc_free_polygon(&clip);
278 gpc_free_polygon(&result);
284 ********************************************************************/