bool GeoClip::ClipPoint(const GeoPoint &origin, GeoPoint &pt) const { const Angle zero = Angle::Zero(); if (pt.longitude < zero) { if (origin.longitude <= zero) return false; pt = clip_longitude(origin, pt, zero); } else if (pt.longitude > width) { if (origin.longitude >= width) return false; pt = clip_longitude(origin, pt, width); } if (pt.latitude < south) { if (origin.latitude <= south) return false; pt = clip_latitude(origin, pt, south); } else if (pt.latitude > north) { if (origin.latitude >= north) return false; pt = clip_latitude(origin, pt, north); } return true; }
std::string olc_manipulate::shorten_single(std::string olc, double latitude, double longitude){ if(!olc_check_full_single(olc)){ throw std::range_error("The Open Location Codes provided must be complete. Incomplete code: " + olc); } if(olc.find(padding) != std::string::npos){ throw std::range_error("The Open Location Codes provided cannot have padding characters. Padded code: " + olc); } for(unsigned int i = 0; i < olc.size(); i++){ olc[i] = toupper(olc[i]); } std::vector < double > decoded_code = olc_decode_single(olc); if(decoded_code[6] < min_trim_length){ throw std::range_error("Open Location Codes must be >6 in length to be shortened. Offending code: " + olc); } longitude = clip_longitude(longitude); latitude = clip_lat(latitude); double range = std::max(std::abs((double) decoded_code[5] - longitude), std::abs((double) decoded_code[4] - latitude)); for(unsigned int i = resolution_levels.size() - 2; i >= 1; i--){ if(range < (resolution_levels[i] * 0.3)){ return olc.substr((i+1)*2); } } return olc; }
std::string olc_manipulate::recover_single(std::string olc, double latitude, double longitude){ if(!olc_check_short_single(olc)){ if(olc_check_full_single(olc)){ return olc; } throw std::range_error("codes provided to recover_olc must be valid short Open Location Codes. Offending code: " + olc); } double ref_longitude = clip_longitude(longitude); double ref_latitude = clip_lat(latitude); for(unsigned int i = 0; i < olc.size(); i++){ olc[i] = toupper(olc[i]); } int padding_length = (separator_position - olc.find(separator)); double resolution = pow(20.0, (2.0 - (padding_length / 2.0))); double area_to_edge = resolution / 2.0; double round_lat = ref_latitude / resolution; double round_long = ref_longitude / resolution; std::vector < double > code_area = olc_decode_single( olc_encode_single(round_lat, round_long, max_pair_length).substr(0, padding_length) + olc ); double degrees_difference = (code_area[4] - ref_latitude); if(degrees_difference > area_to_edge){ code_area[4] -= resolution; } else if(degrees_difference < -area_to_edge){ code_area[4] += resolution; } degrees_difference = (code_area[5] - ref_longitude); if(degrees_difference > area_to_edge){ code_area[5] -= resolution; } else if(degrees_difference < -area_to_edge){ code_area[5] += resolution; } return(olc_encode_single(code_area[4], code_area[5], code_area[6])); }
static unsigned ClipVertexLongitude(const Angle west, const Angle east, const GeoPoint &prev, GeoPoint &pt, GeoPoint &insert, const GeoPoint &next) { unsigned num_insert = 0; if (pt.longitude < west) { if (prev.longitude <= west) { if (next.longitude <= west) /* all three outside, middle one can be deleted */ return 0; pt = clip_longitude(next, pt, west); } else { if (next.longitude > west) { /* both neighbours are inside, clip both lines and insert a new vertex */ insert = clip_longitude(next, pt, west); ++num_insert; } pt = clip_longitude(prev, pt, west); } } else if (pt.longitude > east) { if (prev.longitude >= east) { if (next.longitude >= east) /* all three outside, middle one can be deleted */ return 0; pt = clip_longitude(next, pt, east); } else { if (next.longitude < east) { /* both neighbours are inside, clip both lines and insert a new vertex */ insert = clip_longitude(next, pt, east); ++num_insert; } pt = clip_longitude(prev, pt, east); } } return 1 + num_insert; }