Example #1
0
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));
}
Example #2
0
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;
}