annotate DEPENDENCIES/generic/include/boost/polygon/detail/polygon_simplify.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright 2011, Andrew Ross
Chris@16 2 //
Chris@16 3 // Use, modification and distribution are subject to the Boost Software License,
Chris@16 4 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 5 // http://www.boost.org/LICENSE_1_0.txt).
Chris@16 6 #ifndef BOOST_POLYGON_DETAIL_SIMPLIFY_HPP
Chris@16 7 #define BOOST_POLYGON_DETAIL_SIMPLIFY_HPP
Chris@16 8 #include <vector>
Chris@16 9
Chris@16 10 namespace boost { namespace polygon { namespace detail { namespace simplify_detail {
Chris@16 11
Chris@16 12 // Does a simplification/optimization pass on the polygon. If a given
Chris@16 13 // vertex lies within "len" of the line segment joining its neighbor
Chris@16 14 // vertices, it is removed.
Chris@16 15 template <typename T> //T is a model of point concept
Chris@16 16 std::size_t simplify(std::vector<T>& dst, const std::vector<T>& src,
Chris@16 17 typename coordinate_traits<
Chris@16 18 typename point_traits<T>::coordinate_type
Chris@16 19 >::coordinate_distance len)
Chris@16 20 {
Chris@16 21 using namespace boost::polygon;
Chris@16 22 typedef typename point_traits<T>::coordinate_type coordinate_type;
Chris@16 23 typedef typename coordinate_traits<coordinate_type>::area_type ftype;
Chris@16 24 typedef typename std::vector<T>::const_iterator iter;
Chris@16 25
Chris@16 26 std::vector<T> out;
Chris@16 27 out.reserve(src.size());
Chris@16 28 dst = src;
Chris@16 29 std::size_t final_result = 0;
Chris@16 30 std::size_t orig_size = src.size();
Chris@16 31
Chris@16 32 //I can't use == if T doesn't provide it, so use generic point concept compare
Chris@16 33 bool closed = equivalence(src.front(), src.back());
Chris@16 34
Chris@16 35 //we need to keep smoothing until we don't find points to remove
Chris@16 36 //because removing points in the first iteration through the
Chris@16 37 //polygon may leave it in a state where more removal is possible
Chris@16 38 bool not_done = true;
Chris@16 39 while(not_done) {
Chris@16 40 if(dst.size() < 3) {
Chris@16 41 dst.clear();
Chris@16 42 return orig_size;
Chris@16 43 }
Chris@16 44
Chris@16 45 // Start with the second, test for the last point
Chris@16 46 // explicitly, and exit after looping back around to the first.
Chris@16 47 ftype len2 = ftype(len) * ftype(len);
Chris@16 48 for(iter prev=dst.begin(), i=prev+1, next; /**/; i = next) {
Chris@16 49 next = i+1;
Chris@16 50 if(next == dst.end())
Chris@16 51 next = dst.begin();
Chris@16 52
Chris@16 53 // points A, B, C
Chris@16 54 ftype ax = x(*prev), ay = y(*prev);
Chris@16 55 ftype bx = x(*i), by = y(*i);
Chris@16 56 ftype cx = x(*next), cy = y(*next);
Chris@16 57
Chris@16 58 // vectors AB, BC and AC:
Chris@16 59 ftype abx = bx-ax, aby = by-ay;
Chris@16 60 ftype bcx = cx-bx, bcy = cy-by;
Chris@16 61 ftype acx = cx-ax, acy = cy-ay;
Chris@16 62
Chris@16 63 // dot products
Chris@16 64 ftype ab_ab = abx*abx + aby*aby;
Chris@16 65 ftype bc_bc = bcx*bcx + bcy*bcy;
Chris@16 66 ftype ac_ac = acx*acx + acy*acy;
Chris@16 67 ftype ab_ac = abx*acx + aby*acy;
Chris@16 68
Chris@16 69 // projection of AB along AC
Chris@16 70 ftype projf = ab_ac / ac_ac;
Chris@16 71 ftype projx = acx * projf, projy = acy * projf;
Chris@16 72
Chris@16 73 // perpendicular vector from the line AC to point B (i.e. AB - proj)
Chris@16 74 ftype perpx = abx - projx, perpy = aby - projy;
Chris@16 75
Chris@16 76 // Squared fractional distance of projection. FIXME: can
Chris@16 77 // remove this division, the decisions below can be made with
Chris@16 78 // just the sign of the quotient and a check to see if
Chris@16 79 // abs(numerator) is greater than abs(divisor).
Chris@16 80 ftype f2 = (projx*acx + projy*acx) / ac_ac;
Chris@16 81
Chris@16 82 // Square of the relevant distance from point B:
Chris@16 83 ftype dist2;
Chris@16 84 if (f2 < 0) dist2 = ab_ab;
Chris@16 85 else if(f2 > 1) dist2 = bc_bc;
Chris@16 86 else dist2 = perpx*perpx + perpy*perpy;
Chris@16 87
Chris@16 88 if(dist2 > len2) {
Chris@16 89 prev = i; // bump prev, we didn't remove the segment
Chris@16 90 out.push_back(*i);
Chris@16 91 }
Chris@16 92
Chris@16 93 if(i == dst.begin())
Chris@16 94 break;
Chris@16 95 }
Chris@16 96 std::size_t result = dst.size() - out.size();
Chris@16 97 if(result == 0) {
Chris@16 98 not_done = false;
Chris@16 99 } else {
Chris@16 100 final_result += result;
Chris@16 101 dst = out;
Chris@16 102 out.clear();
Chris@16 103 }
Chris@16 104 } //end of while loop
Chris@16 105 if(closed) {
Chris@16 106 //if the input was closed we want the output to be closed
Chris@16 107 --final_result;
Chris@16 108 dst.push_back(dst.front());
Chris@16 109 }
Chris@16 110 return final_result;
Chris@16 111 }
Chris@16 112
Chris@16 113
Chris@16 114 }}}}
Chris@16 115
Chris@16 116 #endif