static PyObject *Polygon_area(Polygon *self, PyObject *args) { int i=INDEF; if (! PyArg_ParseTuple(args, "|i", &i)) return Polygon_Raise(ERR_ARG); if (i!=INDEF) { if ((i >= 0) && (i < self->p->num_contours)) return Py_BuildValue("d", poly_c_area(self->p->contour+i)); else return Polygon_Raise(ERR_IND); } return Py_BuildValue("d", poly_p_area(self->p)); }
static PyObject *Polygon_sample(Polygon *self, PyObject *args) { PyObject *rng, *val1, *val2, *val3, *res; double A; if (! PyArg_ParseTuple(args, "O", &rng)) return Polygon_Raise(ERR_ARG); if (!PyCallable_Check(rng)) return Polygon_Raise(ERR_ARG); res = NULL; Py_INCREF(rng); // Sampling requires three random values val1 = val2 = val3 = NULL; val1 = PyObject_CallObject(rng, NULL); val2 = PyObject_CallObject(rng, NULL); val3 = PyObject_CallObject(rng, NULL); Py_DECREF(rng); if ((! PyFloat_Check(val1)) || (! PyFloat_Check(val2)) || (! PyFloat_Check(val3))) { Polygon_Raise(PolyError, "rng returned something other than a float"); goto cleanup; } A = poly_p_area(self->gpc_p); if (A == 0.0) { Polygon_Raise(PolyError, "cannot sample from a zero-area polygon"); goto cleanup; } else { gpc_tristrip *t = (gpc_tristrip *)alloca(sizeof(gpc_tristrip)); gpc_vertex_list *vl; gpc_vertex_list one_tri; int i, j; gpc_vertex *tri_verts; double a, b, c, px, py; t->num_strips = 0; t->strip = NULL; gpc_polygon_to_tristrip(self->gpc_p, t); A *= PyFloat_AS_DOUBLE(val1); one_tri.num_vertices = 3; for (i=0; i < t->num_strips; i++) { vl = t->strip + i; for (j=0; j < vl->num_vertices - 2; j++) { one_tri.vertex = vl->vertex + j; A -= poly_c_area(& one_tri); if (A <= 0.0) goto tri_found; } } tri_found: // sample a point from this triangle a = PyFloat_AS_DOUBLE(val2); b = PyFloat_AS_DOUBLE(val3); if ((a + b) > 1.0) { a = 1 - a; b = 1 - b; } c = 1 - a - b; tri_verts = one_tri.vertex; px = a * tri_verts[0].x + b * tri_verts[1].x + c * tri_verts[2].x; py = a * tri_verts[0].y + b * tri_verts[1].y + c * tri_verts[2].y; res = PyTuple_New(2); PyTuple_SetItem(res, 0, PyFloat_FromDouble(px)); PyTuple_SetItem(res, 1, PyFloat_FromDouble(py)); gpc_free_tristrip(t); } cleanup: Py_XDECREF(val1); Py_XDECREF(val2); Py_XDECREF(val3); return res; }