Changeset 410

Show
Ignore:
Timestamp:
10/23/06 19:23:13 (2 years ago)
Author:
sgillies
Message:

add methods to prune empty nodes from trees and dump the tree out to a nested dict

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • Quadtree/trunk/quadtree/_treemodule.c

    r407 r410  
    4141Quadtree_add(Quadtree *self, PyObject *args) 
    4242{ 
    43     int n; 
     43    int n, size; 
     44    PyObject *bounds=NULL; 
    4445    double min[2], max[2]; 
    4546    SHPObject *s; 
     
    4950    double x[5], y[5]; 
    5051     
    51     if (!PyArg_ParseTuple(args, "i(dddd)", &n, 
    52                           &min[0], &min[1], &max[0], &max[1])) 
    53         return NULL; 
    54  
     52    if (!PyArg_ParseTuple(args, "iO", &n, &bounds)) 
     53        return NULL; 
     54 
     55    /* Check length of the bounds argument */ 
     56    if (!PySequence_Check(bounds)) 
     57    { 
     58        PyErr_SetString(PyExc_TypeError, "Bounds must be a sequence"); 
     59        return NULL; 
     60    } 
     61 
     62    size = (int) PySequence_Size(bounds); 
     63    if (size == 2) 
     64    { 
     65        min[0] = max[0] = PyFloat_AsDouble(PySequence_ITEM(bounds, 0)); 
     66        min[1] = max[1] = PyFloat_AsDouble(PySequence_ITEM(bounds, 1)); 
     67    } 
     68    else if (size == 4) 
     69    { 
     70        min[0] = PyFloat_AsDouble(PySequence_ITEM(bounds, 0)); 
     71        min[1] = PyFloat_AsDouble(PySequence_ITEM(bounds, 1)); 
     72        max[0] = PyFloat_AsDouble(PySequence_ITEM(bounds, 2)); 
     73        max[1] = PyFloat_AsDouble(PySequence_ITEM(bounds, 3)); 
     74    } 
     75    else 
     76    { 
     77        PyErr_Format(PyExc_TypeError, 
     78            "Bounds argument must be sequence of length 2 or 4, not %d", 
     79            size); 
     80        return NULL; 
     81    } 
     82     
    5583    /* make shape vertices */ 
    5684    x[0] = min[0]; 
     
    79107} 
    80108 
     109static PyObject * 
     110Quadtree_prune(Quadtree *self) 
     111{ 
     112    SHPTreeTrimExtraNodes(self->tree); 
     113    Py_INCREF(Py_None); 
     114    return Py_None; 
     115} 
     116 
     117/* Tree structure */ 
     118 
     119static void  
     120QuadtreeNodeDump(SHPTreeNode *node, PyObject *nodelist) 
     121{ 
     122    int i; 
     123    PyObject *g=NULL, *ids=NULL, *bounds=NULL, *children=NULL; 
     124 
     125    g = PyDict_New(); 
     126     
     127    /* Save bounds */ 
     128    bounds = Py_BuildValue("(dddd)",  
     129                node->adfBoundsMin[0], node->adfBoundsMin[1],  
     130                node->adfBoundsMax[0], node->adfBoundsMax[1]);  
     131    PyDict_SetItemString(g, "bounds", bounds); 
     132  
     133    /* Save ids */ 
     134    ids = PyList_New(0); 
     135    for (i=0; i<node->nShapeCount; i++) 
     136    { 
     137        PyList_Append(ids, Py_BuildValue("i", node->panShapeIds[i])); 
     138    } 
     139    PyDict_SetItemString(g, "ids", ids); 
     140 
     141    /* Child nodes */ 
     142    children = PyList_New(0); 
     143    for (i=0; i<node->nSubNodes; i++) 
     144    { 
     145        if (node->apsSubNode[i] != NULL) 
     146            QuadtreeNodeDump(node->apsSubNode[i], children); 
     147    } 
     148    PyDict_SetItemString(g, "nodes", children); 
     149     
     150    /* Add g to the node list */ 
     151    PyList_Append(nodelist, g); 
     152} 
     153 
     154static PyObject * 
     155Quadtree_struct(Quadtree *self) 
     156{ 
     157    PyObject *nodes=NULL; 
     158    nodes = PyList_New(0); 
     159    QuadtreeNodeDump(self->tree->psRoot, nodes); 
     160    return PyList_GetItem(nodes, 0); 
     161} 
    81162 
    82163static PyObject * 
     
    104185static PyMethodDef module_methods[] = { 
    105186    {"add", (PyCFunction)Quadtree_add, METH_VARARGS, "Add an item to an index, specifying an integer id and a bounding box"}, 
     187    {"prune", (PyCFunction)Quadtree_prune, METH_NOARGS, "Remove unused nodes from the tree"}, 
     188    {"struct", (PyCFunction)Quadtree_struct, METH_NOARGS, "Return simple graph structure of the tree"}, 
    106189    {"likely_intersection", (PyCFunction)Quadtree_intersection, METH_VARARGS, "Return an iterator over integer ids of items that are likely to intersect with the specified bounding box."}, 
    107190    {NULL} 
  • Quadtree/trunk/tests/QuadTree.txt

    r396 r410  
    77    >>> index = Quadtree((-180, -90, 180, 90), maxdepth=16) 
    88 
    9 Add 3 items 
     9Add 4 items, the last one a point 
    1010 
    1111    >>> index.add(0, [-106, 39, -105, 40]) 
    1212    >>> index.add(1, (-100, 25, -95, 30)) 
    1313    >>> index.add(2, (40, 50, 45, 55)) 
     14    >>> index.add(3, (-105, 33)) 
     15 
     16Prune 
     17 
     18    >>> index.prune() 
    1419 
    1520Find likely items 
    1621 
    1722    >>> [n for n in index.likely_intersection([-110, 30, -100, 45])] 
    18     [0, 1
     23    [0, 1, 3
    1924    >>> [n for n in index.likely_intersection([10, 40, 40.05, 60])] 
    2025    [2] 
     
    2631    >>> [n for n in index.likely_intersection([-110, 35, -108, 45])] 
    2732    [0] 
     33    
     34Tree structure 
     35 
     36    >>> tree = index.struct() 
    2837     
     38Visualize 
     39 
     40    >>> from quadtree.viz import render_graph 
     41    >>> render_graph(tree, 'quadtree.png') 
     42     
     43 
  • Quadtree/trunk/tests/benchmarks.py

    r399 r410  
    1818 
    1919# Scatter points randomly in a 1x1 box 
    20 count = 1000 
    21 index_extent = [-180, -90, 180, 90] 
     20count = 50000 
     21index_extent = (-180, -90, 180, 90) 
    2222points = [] 
    2323index = Quadtree(index_extent) 
    2424for i in xrange(count): 
    25     x = random.random(
    26     y = random.random(
     25    x = 360.0*(random.random()-0.5
     26    y = 180.0*(random.random()-0.5
    2727    points.append(Point(x, y)) 
    28     index.add(i, [x, y, x, y]
     28    index.add(i, (x, y)
    2929 
    30 bbox = [0.2, 0.3, 0.3, 0.4] 
     30bbox = (0.0, 50.0, 5.0, 55.0) 
    3131 
    3232print count, "points" 
  • Quadtree/trunk/tests/runtests

    r396 r410  
    11#!/bin/sh 
    2 PYTHONPATH=/home/sean/Projects/dev-packages python runalltests.py 
     2PYTHONPATH=/home/sean/Projects/PCL-trunk/dev-packages python runalltests.py 
    33