Example #1
0
// Depth-first traverse, assigning parent pointers (s=self ind, p=parent ind)
// Returns the number of points contained in the bounding box for that node
fsp_t assign_parents(FS_TNODE * T, fsp_t s, fsp_t p)
{
    T[s].p = p; //assign pointer to parent for this node
    if (T[s].c2 >= 0) { //if internal node (not leaf)
        assign_parents(T, T[s].c1, s); //make child point to me
        assign_parents(T, T[s].c2, s); //make 2nd child point to me, summing points
    }
    return 1;
}
Example #2
0
inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
            Geometry2 const& geometry2,
            OutputIterator out)
{
    typedef std::deque
        <
            typename geometry::ring_type<GeometryOut>::type
        > ring_container_type;

    typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;

    // Union: return either of them
    // Intersection: return nothing
    // Difference: return first of them
    if (Direction == overlay_intersection
        || (Direction == overlay_difference
            && geometry::num_points(geometry1) == 0))
    {
        return out;
    }

    std::map<ring_identifier, int> empty;
    std::map<ring_identifier, properties> all_of_one_of_them;

    select_rings<Direction>(geometry1, geometry2, empty, all_of_one_of_them, false);
    ring_container_type rings;
    assign_parents(geometry1, geometry2, rings, all_of_one_of_them);
    return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
}
inline void assign_parents(Geometry const& geometry,
            RingCollection const& collection,
            RingMap& ring_map,
            bool check_for_orientation)
{
    // Call it with an empty geometry as second geometry (source_id == 1)
    // (ring_map should be empty for source_id==1)

    Geometry empty;
    assign_parents(geometry, empty, collection, ring_map, check_for_orientation);
}
inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
            Geometry2 const& geometry2,
            OutputIterator out, Strategy const& strategy)
{
    typedef std::deque
        <
            typename geometry::ring_type<GeometryOut>::type
        > ring_container_type;

    typedef typename geometry::point_type<Geometry1>::type point_type1;

    typedef ring_properties
        <
            point_type1,
            typename Strategy::template area_strategy
                <
                    point_type1
                >::type::return_type
        > properties;

// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4127)
#endif

    // Union: return either of them
    // Intersection: return nothing
    // Difference: return first of them
    if (OverlayType == overlay_intersection
        || (OverlayType == overlay_difference && geometry::is_empty(geometry1)))
    {
        return out;
    }

#if defined(_MSC_VER)
#pragma warning(pop)
#endif


    std::map<ring_identifier, ring_turn_info> empty;
    std::map<ring_identifier, properties> all_of_one_of_them;

    select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them, strategy);
    ring_container_type rings;
    assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy);
    return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
}
Example #5
0
inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
            Geometry2 const& geometry2,
            OutputIterator out)
{
    typedef std::deque
        <
            typename geometry::ring_type<GeometryOut>::type
        > ring_container_type;

    typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;

// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4127)
#endif

    // Union: return either of them
    // Intersection: return nothing
    // Difference: return first of them
    if (Direction == overlay_intersection
        || (Direction == overlay_difference
            && geometry::num_points(geometry1) == 0))
    {
        return out;
    }

#if defined(_MSC_VER)
#pragma warning(pop)
#endif


    std::map<ring_identifier, int> empty;
    std::map<ring_identifier, properties> all_of_one_of_them;

    select_rings<Direction>(geometry1, geometry2, empty, all_of_one_of_them, false);
    ring_container_type rings;
    assign_parents(geometry1, geometry2, rings, all_of_one_of_them);
    return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
}
Example #6
0
    static inline OutputIterator apply(
                Geometry1 const& geometry1, Geometry2 const& geometry2,
                RobustPolicy const& robust_policy,
                OutputIterator out,
                Strategy const& )
    {
        if ( geometry::num_points(geometry1) == 0
          && geometry::num_points(geometry2) == 0 )
        {
            return out;
        }

        if ( geometry::num_points(geometry1) == 0
          || geometry::num_points(geometry2) == 0 )
        {
            return return_if_one_input_is_empty
                <
                    GeometryOut, Direction, ReverseOut
                >(geometry1, geometry2, out);
        }

        typedef typename geometry::point_type<GeometryOut>::type point_type;
        typedef detail::overlay::traversal_turn_info
        <
            point_type,
            typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
        > turn_info;
        typedef std::deque<turn_info> container_type;

        typedef std::deque
            <
                typename geometry::ring_type<GeometryOut>::type
            > ring_container_type;

        container_type turn_points;

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        boost::timer timer;
#endif

#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "get turns" << std::endl;
#endif
        detail::get_turns::no_interrupt_policy policy;
        geometry::get_turns
            <
                Reverse1, Reverse2,
                detail::overlay::assign_null_policy
            >(geometry1, geometry2, robust_policy, turn_points, policy);

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        std::cout << "get_turns: " << timer.elapsed() << std::endl;
#endif

#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
        typename Strategy::side_strategy_type side_strategy;
        geometry::enrich_intersection_points<Reverse1, Reverse2>(turn_points,
                Direction == overlay_union
                    ? geometry::detail::overlay::operation_union
                    : geometry::detail::overlay::operation_intersection,
                    geometry1, geometry2,
                    robust_policy,
                    side_strategy);

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        std::cout << "enrich_intersection_points: " << timer.elapsed() << std::endl;
#endif


#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "traverse" << std::endl;
#endif
        // Traverse through intersection/turn points and create rings of them.
        // Note that these rings are always in clockwise order, even in CCW polygons,
        // and are marked as "to be reversed" below
        ring_container_type rings;
        traverse<Reverse1, Reverse2, Geometry1, Geometry2>::apply
                (
                    geometry1, geometry2,
                    Direction == overlay_union
                        ? geometry::detail::overlay::operation_union
                        : geometry::detail::overlay::operation_intersection,
                    robust_policy,
                    turn_points, rings
                );

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        std::cout << "traverse: " << timer.elapsed() << std::endl;
#endif


        std::map<ring_identifier, int> map;
        map_turns(map, turn_points);

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        std::cout << "map_turns: " << timer.elapsed() << std::endl;
#endif

        typedef ring_properties<typename geometry::point_type<GeometryOut>::type> properties;

        std::map<ring_identifier, properties> selected;
        select_rings<Direction>(geometry1, geometry2, map, selected, ! turn_points.empty());

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        std::cout << "select_rings: " << timer.elapsed() << std::endl;
#endif


        // Add rings created during traversal
        {
            ring_identifier id(2, 0, -1);
            for (typename boost::range_iterator<ring_container_type>::type
                    it = boost::begin(rings);
                 it != boost::end(rings);
                 ++it)
            {
                selected[id] = properties(*it, true);
                selected[id].reversed = ReverseOut;
                id.multi_index++;
            }
        }

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        std::cout << "add traversal rings: " << timer.elapsed() << std::endl;
#endif


        assign_parents(geometry1, geometry2, rings, selected);

#ifdef BOOST_GEOMETRY_TIME_OVERLAY
        std::cout << "assign_parents: " << timer.elapsed() << std::endl;
#endif

        return add_rings<GeometryOut>(selected, geometry1, geometry2, rings, out);
    }
Example #7
0
    static inline OutputIterator apply(
                Geometry1 const& geometry1, Geometry2 const& geometry2,
                RobustPolicy const& robust_policy,
                OutputIterator out,
                Strategy const& )
    {
        bool const is_empty1 = geometry::is_empty(geometry1);
        bool const is_empty2 = geometry::is_empty(geometry2);

        if (is_empty1 && is_empty2)
        {
            return out;
        }

        if (is_empty1 || is_empty2)
        {
            return return_if_one_input_is_empty
                <
                    GeometryOut, Direction, ReverseOut
                >(geometry1, geometry2, out);
        }

        typedef typename geometry::point_type<GeometryOut>::type point_type;
        typedef detail::overlay::traversal_turn_info
        <
            point_type,
            typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
        > turn_info;
        typedef std::deque<turn_info> container_type;

        typedef std::deque
            <
                typename geometry::ring_type<GeometryOut>::type
            > ring_container_type;

        container_type turn_points;

#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "get turns" << std::endl;
#endif
        detail::get_turns::no_interrupt_policy policy;
        geometry::get_turns
            <
                Reverse1, Reverse2,
                detail::overlay::assign_null_policy
            >(geometry1, geometry2, robust_policy, turn_points, policy);

#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
        typename Strategy::side_strategy_type side_strategy;
        geometry::enrich_intersection_points<Reverse1, Reverse2>(turn_points,
                Direction == overlay_union
                    ? geometry::detail::overlay::operation_union
                    : geometry::detail::overlay::operation_intersection,
                    geometry1, geometry2,
                    robust_policy,
                    side_strategy);

#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "traverse" << std::endl;
#endif
        // Traverse through intersection/turn points and create rings of them.
        // Note that these rings are always in clockwise order, even in CCW polygons,
        // and are marked as "to be reversed" below
        ring_container_type rings;
        traverse<Reverse1, Reverse2, Geometry1, Geometry2>::apply
                (
                    geometry1, geometry2,
                    Direction == overlay_union
                        ? geometry::detail::overlay::operation_union
                        : geometry::detail::overlay::operation_intersection,
                    robust_policy,
                    turn_points, rings
                );

        std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
        get_ring_turn_info(turn_info_per_ring, turn_points);

        typedef ring_properties
        <
            typename geometry::point_type<GeometryOut>::type
        > properties;

        // Select all rings which are NOT touched by any intersection point
        std::map<ring_identifier, properties> selected_ring_properties;
        select_rings<Direction>(geometry1, geometry2, turn_info_per_ring,
                selected_ring_properties);

        // Add rings created during traversal
        {
            ring_identifier id(2, 0, -1);
            for (typename boost::range_iterator<ring_container_type>::type
                    it = boost::begin(rings);
                 it != boost::end(rings);
                 ++it)
            {
                selected_ring_properties[id] = properties(*it);
                selected_ring_properties[id].reversed = ReverseOut;
                id.multi_index++;
            }
        }

        assign_parents(geometry1, geometry2, rings, selected_ring_properties);

        return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
    }
Example #8
0
/* Find the fair-split tree for some data, returning the binary tree
   Inputs:
    V - N-by-D array of values
    n - number of points
    d - number of dimensions
    root - will return the index of the root of the tree (also is the number of elements in the tree)
*/
FS_TREE * FAIR_SPLIT(val_t * V, fsp_t n, int d)
{
    int di; //counter thru dimensions
    fsp_t ni; //counter thru datapoints
    FS_LNODE ** DL;
    FS_TREE * T;
    fsp_t * firsts, * lasts; //pointers to first and last elements of lists
    fsp_t ti; //first available element in FST

    // 1. Construct doubly-linked list for each dimension of data
    DL = malloc(d*sizeof(FS_LNODE *)); //a d-length array of pointers to doubly-linked lists
    for (di=0; di<d; di++) { // for each dimension, (NOTE: this is 630mb for 3m spikes and 10dims, in 10 63mb chunks)
        if (!(DL[di] = malloc(n*sizeof(FS_LNODE)))) { //allocate that dim's doubly-linked list
            printf("ERROR in FS_FAIR_SPLIT: cannot allocate memory for doubly-linked lists\n");
        }
        for (ni=0; ni<n; ni++) { //for each node in that new list
            DL[di][ni].data = ni; //pointer to data
            DL[di][ni].adj_n = ni; //pointers to same point in adjacent dimension's lists
            DL[di][ni].adj_p = ni;
        }
    }

    // 2. Sort each dimension's list
    for (di=0; di<d; di++) { // for each dimension,
        FS_MergeSort(DL, V, d, di, n); //sort this dimension's list, keeping track of cross-pointers
    }

    // Set forward/back pointers within each dimension's list (so list pointers go in sorted dir)
    for (di=0; di<d; di++) { // for each dimension,
        for (ni=0; ni<n; ni++) { //for each node
            DL[di][ni].prev = ni-1; //pointer to previous node in list
            DL[di][ni].next = ni+1; //pointer to next node in list
        }
        DL[di][n-1].next = -1; //set last node's next pointer to null (1st's prev will be set in loop)
    }

    // 3. Allocate space for the binary tree
    T = malloc(sizeof(FS_TREE));
    if (!(T->tree = malloc((n+n-1)*sizeof(FS_TNODE)))) { //allocate space, should only be 72mb for 3m spikes
        printf("ERROR in FS_FAIR_SPLIT: cannot allocate memory for FS_TREE's list\n");
    }
    T->d = d; //save the number of dimensions in the tree struct
    T->n = n+n-1; //number of nodes in the tree
    T->V = V; //save pointer to data array in the tree struct
    ti=0; //first available element in FST

    firsts = malloc(d * sizeof(fsp_t));
    lasts = malloc(d * sizeof(fsp_t));

    for (di=0; di<d; di++) { // for each dimension,
        firsts[di] = 0; //sorted, so set first to first
        lasts[di] = n-1; //likewise
    }

    // 4. Recursively form the FS tree
    T->root = FS_RECURSE(T->tree, &ti, DL, V, d, firsts, lasts); //form the tree and save pointer to root

    // 5. Free the linked lists from memory
    for (di=0; di<d; di++) { // for each dimension,
        free(DL[di]); //free that malloc'd block
    }

    // 6. Depth-first traverse the tree, assigning parent backpointers
    assign_parents(T->tree, T->root, -1);

    // free the doubly-linked lists
    free(DL);
    free(firsts);
    free(lasts);

    // Return pointer to the tree
    return T;

}
    static inline OutputIterator apply(
                Geometry1 const& geometry1, Geometry2 const& geometry2,
                RobustPolicy const& robust_policy,
                OutputIterator out,
                Strategy const& strategy,
                Visitor& visitor)
    {
        bool const is_empty1 = geometry::is_empty(geometry1);
        bool const is_empty2 = geometry::is_empty(geometry2);

        if (is_empty1 && is_empty2)
        {
            return out;
        }

        if (is_empty1 || is_empty2)
        {
            return return_if_one_input_is_empty
                <
                    GeometryOut, OverlayType, ReverseOut
                >(geometry1, geometry2, out, strategy);
        }

        typedef typename geometry::point_type<GeometryOut>::type point_type;
        typedef detail::overlay::traversal_turn_info
        <
            point_type,
            typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
        > turn_info;
        typedef std::deque<turn_info> turn_container_type;

        typedef std::deque
            <
                typename geometry::ring_type<GeometryOut>::type
            > ring_container_type;

        // Define the clusters, mapping cluster_id -> turns
        typedef std::map
            <
                signed_size_type,
                cluster_info
            > cluster_type;

        turn_container_type turns;

#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "get turns" << std::endl;
#endif
        detail::get_turns::no_interrupt_policy policy;
        geometry::get_turns
            <
                Reverse1, Reverse2,
                detail::overlay::assign_null_policy
            >(geometry1, geometry2, strategy, robust_policy, turns, policy);

        visitor.visit_turns(1, turns);

#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
        {
            self_get_turn_points::self_turns<Reverse1, assign_null_policy>(geometry1,
                strategy, robust_policy, turns, policy, 0);
            self_get_turn_points::self_turns<Reverse2, assign_null_policy>(geometry2,
                strategy, robust_policy, turns, policy, 1);
        }
#endif


#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
        typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy();
        cluster_type clusters;

        geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
                clusters, geometry1, geometry2,
                    robust_policy,
                    side_strategy);

        visitor.visit_turns(2, turns);

        visitor.visit_clusters(clusters, turns);

#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "traverse" << std::endl;
#endif
        // Traverse through intersection/turn points and create rings of them.
        // Note that these rings are always in clockwise order, even in CCW polygons,
        // and are marked as "to be reversed" below
        ring_container_type rings;
        traverse<Reverse1, Reverse2, Geometry1, Geometry2, OverlayType>::apply
                (
                    geometry1, geometry2,
                    strategy,
                    robust_policy,
                    turns, rings,
                    clusters,
                    visitor
                );

        std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
        get_ring_turn_info<OverlayType>(turn_info_per_ring, turns, clusters);

        typedef typename Strategy::template area_strategy<point_type>::type area_strategy_type;

        typedef ring_properties
            <
                point_type,
                typename area_strategy_type::return_type
            > properties;

        // Select all rings which are NOT touched by any intersection point
        std::map<ring_identifier, properties> selected_ring_properties;
        select_rings<OverlayType>(geometry1, geometry2, turn_info_per_ring,
                selected_ring_properties, strategy);

        // Add rings created during traversal
        {
            area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();

            ring_identifier id(2, 0, -1);
            for (typename boost::range_iterator<ring_container_type>::type
                    it = boost::begin(rings);
                 it != boost::end(rings);
                 ++it)
            {
                selected_ring_properties[id] = properties(*it, area_strategy);
                selected_ring_properties[id].reversed = ReverseOut;
                id.multi_index++;
            }
        }

        assign_parents(geometry1, geometry2, rings, selected_ring_properties, strategy);

        return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
    }