Changeset 461

Show
Ignore:
Timestamp:
11/12/08 18:11:11 (1 year ago)
Author:
aaron
Message:

version 0.2

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/clustr/README

    r460 r461  
    6363Bugs 
    6464---- 
    65 At present, clustr does not handle polygon holes correctly. 
     65Clustr does not use an exceptionally sophisticated algorithm for extracting 
     66polygons from the generated alpha shape, with the result that on occasion 
     67improper or self-intersecting polygons get generated. This can confuse GIS 
     68programs that expect better behaved data sets, and ought to be fixed someday. 
     69 
     70Also, the total count of points input is written to every shape record, which 
     71will be wrong if there are multiple components for a given input tag. This 
     72could be fixed by testing inclusion of each point after the polygons are 
     73constructed, which would lengthen runtime. Cost/benefit? Not sure. 
    6674 
    6775License 
    68 ---- 
     76------- 
    6977 
    7078Copyright (c) 2007-2008 Yahoo! Inc. 
  • trunk/clustr/clustr.cpp

    r460 r461  
    2121#include <stdexcept> 
    2222#include <cmath> 
     23#include <algorithm> 
    2324 
    2425#include <unistd.h>  
     
    7980} 
    8081 
     82bool compare_polygon_sizes (const Polygon &a, const Polygon &b) { 
     83    return a.size() < b.size(); 
     84} 
     85 
     86void attach_interior_rings (vector<Polygon> &input, vector<Polygon> &output, bool verbose = false) { 
     87    unsigned int count = 0; 
     88 
     89    /* First, sort the polygons by area. This guarantees that smaller polygons 
     90     * will wind up inside larger polygons. */ 
     91    sort(input.begin(), input.end(), compare_polygon_sizes); 
     92 
     93    for (vector<Polygon>::iterator it = input.begin(); it != input.end(); it++) { 
     94        bool is_interior_ring = false; 
     95 
     96        for (vector<Polygon>::iterator comp = it + 1; comp != input.end(); comp++) { 
     97            /* check if the first point in the first ring of *it is inside the outer ring 
     98             * of *comp. If it is, then we assume that the entire polygon *it is actually 
     99             * inside *comp. 
     100             * 
     101             * Note that *comp needs to be a simple polygon -- it *should* be but sometimes 
     102             * the polygons that come out of the alpha shape self-intersect at a point. 
     103             * Not sure what to do about this. */ 
     104            if ((*comp)[0].is_simple() && (*comp)[0].encloses((*it)[0][0])) { 
     105                for (Polygon::iterator ring = it->begin(); ring != it->end(); ring++) { 
     106                    // this is actually going to get double-interior rings backwards, 
     107                    // but fixing that means making the logic in 
     108                    // Polygon::push_back a lot more sophisticated... 
     109                    comp->push_back(*ring);  
     110                } 
     111                is_interior_ring = true; 
     112                count++; 
     113                break; 
     114            } 
     115        } 
     116 
     117        if (!is_interior_ring) 
     118            output.push_back(*it); 
     119    } 
     120 
     121    if (verbose && count) 
     122        cerr << count << " interior rings attached." << endl; 
     123} 
     124 
    81125void construct_alpha_shape (Config &config, Shapefile &shape, 
    82126                            vector<Point> &pts, string text) 
     
    84128    coord_type alpha = config.alpha; 
    85129    Mesh mesh(pts.begin(), pts.end(), alpha); 
     130    vector<Polygon> polygons, output; 
    86131 
    87132    if (alpha == 0) { 
     
    96141              " component(s) found for alpha value " << alpha << "." << endl; 
    97142 
    98     for (Mesh::component c = mesh.components_begin(); 
    99          c != mesh.components_end(); c++) { 
     143    for (Mesh::component c = mesh.components_begin(); c != mesh.components_end(); c++) { 
    100144        Polygon poly; 
    101         if (extract_alpha_component(c, poly, config.verbose)) { 
    102             if (config.verbose) 
    103                 cerr << "Writing polygon for tag '" << text << "'." << endl; 
    104             write_polygon_to_shapefile(shape, poly, text, pts.size()); 
    105         } 
     145        if (extract_alpha_component(c, poly, config.verbose)) 
     146            polygons.push_back(poly); 
     147    } 
     148 
     149    attach_interior_rings(polygons, output, config.verbose); 
     150 
     151    if (config.verbose) cerr << "Writing " << output.size() << " polygons to shapefile." << endl; 
     152    for (vector<Polygon>::iterator poly = output.begin(); poly != output.end(); poly++) { 
     153        write_polygon_to_shapefile(shape, *poly, text, pts.size()); // FIXME: size is broken 
    106154    } 
    107155} 
  • trunk/clustr/clustr.h

    r460 r461  
    1717#define CLUSTR_H 
    1818 
    19 #define VERSION     "0.1
     19#define VERSION     "0.2
    2020#define AUTHOR      "Schuyler Erle <schuyler@nocat.net>" 
    2121#define COPYRIGHT   "(c) 2007-2008 Yahoo!, Inc." 
     
    174174        iterator begin (void) { return vertices_begin(); }; 
    175175        iterator end (void) { return vertices_end(); }; 
     176        bool encloses (const Point &p) { bounded_side(p) == CGAL::ON_BOUNDED_SIDE; }; 
    176177    }; 
    177178