static inline void debug_turn(Turn const& t, bool non_crossing) { std::cout << "checking turn @" << geometry::wkt(t.point) << "; " << method_char(t.method) << ":" << operation_char(t.operations[0].operation) << "/" << operation_char(t.operations[1].operation) << "; non-crossing? " << std::boolalpha << non_crossing << std::noboolalpha << std::endl; }
static inline void debug_follow(Turn const& turn, Operation op, int index) { std::cout << index << " at " << op.seg_id << " meth: " << method_char(turn.method) << " op: " << operation_char(op.operation) << " vis: " << visited_char(op.visited) << " of: " << operation_char(turn.operations[0].operation) << operation_char(turn.operations[1].operation) << " " << geometry::wkt(turn.point) << std::endl; }
inline bool has_self_intersections(Geometry const& geometry) { typedef typename point_type<Geometry>::type point_type; typedef detail::overlay::turn_info<point_type> turn_info; std::deque<turn_info> turns; detail::disjoint::disjoint_interrupt_policy policy; geometry::self_turns<detail::overlay::assign_null_policy>(geometry, turns, policy); #ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS bool first = true; #endif for(typename std::deque<turn_info>::const_iterator it = boost::begin(turns); it != boost::end(turns); ++it) { turn_info const& info = *it; bool const both_union_turn = info.operations[0].operation == detail::overlay::operation_union && info.operations[1].operation == detail::overlay::operation_union; bool const both_intersection_turn = info.operations[0].operation == detail::overlay::operation_intersection && info.operations[1].operation == detail::overlay::operation_intersection; bool const valid = (both_union_turn || both_intersection_turn) && (info.method == detail::overlay::method_touch || info.method == detail::overlay::method_touch_interior); if (! valid) { #ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS if (first) { std::cout << "turn points: " << std::endl; first = false; } std::cout << method_char(info.method); for (int i = 0; i < 2; i++) { std::cout << " " << operation_char(info.operations[i].operation); std::cout << " " << info.operations[i].seg_id; } std::cout << " " << geometry::dsv(info.point) << std::endl; #endif #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) throw overlay_invalid_input_exception(); #endif } } return false; }
inline void display(MetaTurn const& meta_turn, std::string const& reason = "") { #ifdef BOOST_GEOMETRY_DEBUG_ENRICH std::cout << meta_turn.index << "\tMethods: " << method_char(meta_turn.turn->method) << " operations: " << operation_char(meta_turn.turn->operations[0].operation) << operation_char(meta_turn.turn->operations[1].operation) << " travels to " << meta_turn.turn->operations[0].enriched.travels_to_ip_index << " and " << meta_turn.turn->operations[1].enriched.travels_to_ip_index //<< " -> " << op_index << " " << reason << std::endl; #endif }
inline void debug_turn(Turn const& turn, Operation op, std::string const& header) { std::cout << header << " at " << op.seg_id << " meth: " << method_char(turn.method) << " op: " << operation_char(op.operation) << " of: " << operation_char(turn.operations[0].operation) << operation_char(turn.operations[1].operation) << " " << geometry::wkt(turn.point) << std::endl; if (boost::contains(header, "Finished")) { std::cout << std::endl; } }
inline void enrich_assign(Container& operations, TurnPoints& turn_points, operation_type for_operation, Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { typedef typename IndexType::type operations_type; typedef typename boost::range_iterator<Container const>::type iterator_type; if (operations.size() > 0) { // Assign travel-to-vertex/ip index for each turning point. // Because IP's are circular, PREV starts at the very last one, // being assigned from the first one. // "next ip on same segment" should not be considered circular. bool first = true; iterator_type it = boost::begin(operations); for (iterator_type prev = it + (boost::size(operations) - 1); it != boost::end(operations); prev = it++) { operations_type& prev_op = turn_points[prev->index].operations[prev->operation_index]; operations_type& op = turn_points[it->index].operations[it->operation_index]; prev_op.enriched.travels_to_ip_index = it->index; prev_op.enriched.travels_to_vertex_index = it->subject.seg_id.segment_index; if (! first && prev_op.seg_id.segment_index == op.seg_id.segment_index) { prev_op.enriched.next_ip_index = it->index; } first = false; } } // DEBUG #ifdef BOOST_GEOMETRY_DEBUG_ENRICH { for (iterator_type it = boost::begin(operations); it != boost::end(operations); ++it) { operations_type& op = turn_points[it->index] .operations[it->operation_index]; std::cout << it->index << " meth: " << method_char(turn_points[it->index].method) << " seg: " << op.seg_id << " dst: " << boost::numeric_cast<double>(op.enriched.distance) << " op: " << operation_char(turn_points[it->index].operations[0].operation) << operation_char(turn_points[it->index].operations[1].operation) << " dsc: " << (turn_points[it->index].discarded ? "T" : "F") << " ->vtx " << op.enriched.travels_to_vertex_index << " ->ip " << op.enriched.travels_to_ip_index << " ->nxt ip " << op.enriched.next_ip_index //<< " vis: " << visited_char(op.visited) << std::endl; ; } } #endif // END DEBUG }
/* * Parse a method pointed by start, end is the last character to check (if NULL * assume that start is a zero terminated string) * => assign enum bit to method. * Returns pointer to next char if parse succeeded * and NULL otherwise. */ char* parse_method(char* start, char* end, unsigned int* method) { int len=0; int max=0; if (!start || !method) { LM_ERR("invalid parameter value\n"); return NULL; } if(end) max = end - start; *method = METHOD_UNDEF; switch (start[0]) { case 'A': case 'a': if(end && max<3) goto unknown; if ((start[1]=='c' || start[1]=='C') && (start[2]=='k' || start[2]=='K')) { *method = METHOD_ACK; len = 3; goto done; } goto unknown; case 'B': case 'b': if(end && max<3) goto unknown; if ((start[1]=='y' || start[1]=='Y') && (start[2]=='e' || start[2]=='E')) { *method = METHOD_BYE; len = 3; goto done; } goto unknown; case 'C': case 'c': if(end && max<6) goto unknown; if ((start[1]=='a' || start[1]=='A') && (start[2]=='n' || start[2]=='N') && (start[3]=='c' || start[3]=='C') && (start[4]=='e' || start[4]=='E') && (start[5]=='l' || start[5]=='L')) { *method = METHOD_CANCEL; len = 6; goto done; } goto unknown; case 'I': case 'i': if(end && max<4) goto unknown; if(start[1]=='n' && start[1]=='N') goto unknown; if ((start[2]=='f' || start[2]=='F') && (start[3]=='o' || start[3]=='O')) { *method = METHOD_INFO; len = 4; goto done; } if(end && max<6) goto unknown; if ((start[2]=='v' || start[2]=='V') && (start[3]=='i' || start[3]=='I') && (start[4]=='t' || start[4]=='T') && (start[5]=='e' || start[5]=='E')) { *method = METHOD_INVITE; len = 6; goto done; } goto unknown; case 'M': case 'm': if(end && max<7) goto unknown; if ((start[1]=='e' || start[1]=='E') && (start[2]=='s' || start[2]=='S') && (start[3]=='s' || start[3]=='S') && (start[4]=='a' || start[4]=='A') && (start[5]=='g' || start[5]=='G') && (start[6]=='e' || start[6]=='E')) { *method = METHOD_MESSAGE; len = 7; goto done; } goto unknown; case 'N': case 'n': if(end && max<6) goto unknown; if ((start[1]=='o' || start[1]=='O') && (start[2]=='t' || start[2]=='T') && (start[3]=='i' || start[3]=='I') && (start[4]=='f' || start[4]=='F') && (start[5]=='y' || start[5]=='Y')) { *method = METHOD_NOTIFY; len = 6; goto done; } goto unknown; case 'O': case 'o': if(end && max<7) goto unknown; if((start[1]=='p' || start[1]=='P') && (start[2]=='t' || start[2]=='T') && (start[3]=='i' || start[3]=='I') && (start[4]=='o' || start[4]=='O') && (start[5]=='n' || start[5]=='N') && (start[6]=='s' || start[6]=='S')) { *method = METHOD_OPTIONS; len = 7; goto done; } goto unknown; case 'P': case 'p': if(end && max<5) goto unknown; if((start[1]=='r' || start[1]=='R') && (start[2]=='a' || start[2]=='A') && (start[3]=='c' || start[3]=='C') && (start[4]=='k' || start[4]=='K')) { *method = METHOD_PRACK; len = 5; goto done; } if(end && max<7) goto unknown; if ((start[1]=='u' || start[1]=='U') && (start[2]=='b' || start[2]=='B') && (start[3]=='l' || start[3]=='L') && (start[4]=='i' || start[4]=='I') && (start[5]=='s' || start[5]=='S') && (start[6]=='h' || start[6]=='H')) { *method = METHOD_PUBLISH; len = 7; goto done; } goto unknown; case 'R': case 'r': if(end && max<5) goto unknown; if(start[1]!='e' && start[1]!='E') goto unknown; if((start[2]=='f' || start[2]=='F') && (start[3]=='e' || start[3]=='E') && (start[4]=='R' || start[4]=='R')) { *method = METHOD_REFER; len = 5; goto done; } if(end && max<8) goto unknown; if ((start[2]=='g' || start[2]=='G') && (start[3]=='i' || start[3]=='I') && (start[4]=='s' || start[4]=='S') && (start[5]=='t' || start[5]=='T') && (start[6]=='e' || start[6]=='E') && (start[7]=='r' || start[7]=='R')) { *method = METHOD_REGISTER; len = 8; goto done; } goto unknown; case 'S': case 's': if(end && max<9) goto unknown; if ((start[1]=='u' || start[1]=='U') && (start[2]=='b' || start[2]=='B') && (start[3]=='s' || start[3]=='S') && (start[4]=='c' || start[4]=='C') && (start[5]=='r' || start[5]=='R') && (start[6]=='i' || start[6]=='I') && (start[7]=='b' || start[7]=='B') && (start[8]=='e' || start[8]=='E')) { *method = METHOD_SUBSCRIBE; len = 9; goto done; } goto unknown; case 'U': case 'u': if(end && max<6) goto unknown; if ((start[1]=='p' || start[1]=='P') && (start[2]=='d' || start[2]=='D') && (start[3]=='a' || start[3]=='A') && (start[4]=='t' || start[4]=='T') && (start[5]=='e' || start[5]=='E')) { *method = METHOD_UPDATE; len = 6; goto done; } goto unknown; default: goto unknown; } done: if(!end || (end && len < max)) { if(start[len]!='\0' && start[len]!=',' && start[len]!=' ' && start[len]!='\t' && start[len]!='\r' && start[len]!='\n') goto unknown; } return (start+len); unknown: update_stat(unsupported_methods, 1); *method = METHOD_OTHER; if(end) { while(len < max) { if((start[len]=='\0' || start[len]==',' || start[len]==' ' || start[len]=='\t' || start[len]=='\r' || start[len]=='\n')) return (start+len); if(!method_char(start[len])) { LM_ERR("invalid character %c\n", start[len]); return NULL; } len++; } return end; } while(start[len]!='\0' && start[len]!=',' && start[len]!=' ' && start[len]!='\t' && start[len]!='\r' && start[len]!='\n') { if(!method_char(start[len])) { LM_ERR("invalid character %c!\n", start[len]); return NULL; } len++; } return (start+len); }
inline void enrich_assign(Operations& operations, Turns& turns) { typedef typename boost::range_value<Turns>::type turn_type; typedef typename turn_type::turn_operation_type op_type; typedef typename boost::range_iterator<Operations>::type iterator_type; if (operations.size() > 0) { // Assign travel-to-vertex/ip index for each turning point. // Iterator "next" is circular geometry::ever_circling_range_iterator<Operations const> next(operations); ++next; for (iterator_type it = boost::begin(operations); it != boost::end(operations); ++it) { turn_type& turn = turns[it->turn_index]; op_type& op = turn.operations[it->operation_index]; // Normal behaviour: next should point at next turn: if (it->turn_index == next->turn_index) { ++next; } // Cluster behaviour: next should point after cluster, unless // their seg_ids are not the same while (turn.cluster_id != -1 && it->turn_index != next->turn_index && turn.cluster_id == turns[next->turn_index].cluster_id && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id) { ++next; } turn_type const& next_turn = turns[next->turn_index]; op_type const& next_op = next_turn.operations[next->operation_index]; op.enriched.travels_to_ip_index = static_cast<signed_size_type>(next->turn_index); op.enriched.travels_to_vertex_index = next->subject->seg_id.segment_index; if (op.seg_id.segment_index == next_op.seg_id.segment_index && op.fraction < next_op.fraction) { // Next turn is located further on same segment // assign next_ip_index // (this is one not circular therefore fraction is considered) op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index); } } } // DEBUG #ifdef BOOST_GEOMETRY_DEBUG_ENRICH { for (iterator_type it = boost::begin(operations); it != boost::end(operations); ++it) { op_type& op = turns[it->turn_index] .operations[it->operation_index]; std::cout << it->turn_index << " cl=" << turns[it->turn_index].cluster_id << " meth=" << method_char(turns[it->turn_index].method) << " seg=" << op.seg_id << " dst=" << op.fraction // needs define << " op=" << operation_char(turns[it->turn_index].operations[0].operation) << operation_char(turns[it->turn_index].operations[1].operation) << " (" << operation_char(op.operation) << ")" << " nxt=" << op.enriched.next_ip_index << " / " << op.enriched.travels_to_ip_index << " [vx " << op.enriched.travels_to_vertex_index << "]" << std::endl; ; } } #endif // END DEBUG }