// 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; }
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); }
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); }
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); }
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); }
/* 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); }