// simplifyDP(): // This is the Douglas-Peucker recursive simplification routine // It just marks vertices that are part of the simplified polyline // for approximating the polyline subchain v[j] to v[k]. // Input: tol = approximation tolerance // v[] = polyline array of vertex points // j,k = indices for the subchain v[j] to v[k] // Output: mk[] = array of markers matching vertex array v[] void Contour::simplifyDP(float tol, std::vector<frsmPoint> &v, int j, int k, std::vector<bool> &mk) { if (k <= j + 1) // there is nothing to simplify return; // check for adequate approximation by segment S from v[j] to v[k] int maxi = j; // index of vertex farthest from segment float max_dist_to_seg = 0; // test each vertex v[i] for max distance from segment v[j]-v[k] for (int i = j + 1; i < k; i++) { double dist_to_seg = frsm_dist_to_segment(&v[i], &v[j], &v[k]); if (dist_to_seg <= max_dist_to_seg) continue; else { // v[i] is a new max vertex maxi = i; max_dist_to_seg = dist_to_seg; } } if (max_dist_to_seg > tol) // error is worse than the tolerance { // split the polyline at the farthest vertex mk[maxi] = true; // mark v[maxi] for the simplified polyline // recursively simplify the two subpolylines at v[maxi] simplifyDP(tol, v, j, maxi, mk); // polyline v[j] to v[maxi] simplifyDP(tol, v, maxi, k, mk); // polyline v[maxi] to v[k] } // else the approximation is OK, so ignore intermediate vertices return; }
static void simplifyDP(float tol, ofPoint* v, int j, int k, int* mk ){ if (k <= j+1) // there is nothing to simplify return; // check for adequate approximation by segment S from v[j] to v[k] int maxi = j; // index of vertex farthest from S float maxd2 = 0; // distance squared of farthest vertex float tol2 = tol * tol; // tolerance squared Segment S = {v[j], v[k]}; // segment from v[j] to v[k] ofPoint u; u = S.P1 - S.P0; // segment direction vector double cu = dot(u,u); // segment length squared // test each vertex v[i] for max distance from S // compute using the Feb 2001 Algorithm's dist_ofPoint_to_Segment() // Note: this works in any dimension (2D, 3D, ...) ofPoint w; ofPoint Pb; // base of perpendicular from v[i] to S float b, cw, dv2; // dv2 = distance v[i] to S squared for (int i=j+1; i<k; i++){ // compute distance squared w = v[i] - S.P0; cw = dot(w,u); if ( cw <= 0 ) dv2 = d2(v[i], S.P0); else if ( cu <= cw ) dv2 = d2(v[i], S.P1); else { b = (float)(cw / cu); Pb = S.P0 + u*b; dv2 = d2(v[i], Pb); } // test with current max distance squared if (dv2 <= maxd2) continue; // v[i] is a new max vertex maxi = i; maxd2 = dv2; } if (maxd2 > tol2) // error is worse than the tolerance { // split the polyline at the farthest vertex from S mk[maxi] = 1; // mark v[maxi] for the simplified polyline // recursively simplify the two subpolylines at v[maxi] simplifyDP( tol, v, j, maxi, mk ); // polyline v[j] to v[maxi] simplifyDP( tol, v, maxi, k, mk ); // polyline v[maxi] to v[k] } // else the approximation is OK, so ignore intermediate vertices return; }
void Contour::simplify(float tol) { int n = points.size(); int pv; // misc counters // STAGE 1. Vertex Reduction within tolerance of prior vertex cluster int m = 1;// first point always kept for (int i = 1, pv = 0; i < n - 1; i++) { if (frsm_dist(&points[i], &points[pv]) < tol) continue; points[m] = points[i]; pv = m++; } points[m++] = points[n - 1]; //make sure end is added //m vertices in vertex reduced polyline points.resize(m); // STAGE 2. Douglas-Peucker polyline simplification vector<bool> mk(points.size(), false); mk[0] = mk.back() = 1; // mark the first and last vertices simplifyDP(tol, points, 0, points.size() - 1, mk); // copy marked vertices to the output simplified polyline m = 0; for (int i = 0; i < points.size(); i++) { if (mk[i]) points[m++] = points[i]; //m<=i; } //m vertices in simplified polyline points.resize(m); }
void simplify(std::vector<glm::vec3> &_pts, float _tolerance){ if(_pts.size() < 2) return; int n = _pts.size(); if(n == 0) { return; } std::vector<glm::vec3> sV; sV.resize(n); int i, k, m, pv; // misc counters float tol2 = _tolerance * _tolerance; // tolerance squared std::vector<glm::vec3> vt; std::vector<int> mk; vt.resize(n); mk.resize(n,0); // STAGE 1. Vertex Reduction within tolerance of prior vertex cluster vt[0] = _pts[0]; // start at the beginning for (i=k=1, pv=0; i<n; i++) { if (d2(_pts[i], _pts[pv]) < tol2) continue; vt[k++] = _pts[i]; pv = i; } if (pv < n-1) vt[k++] = _pts[n-1]; // finish at the end // STAGE 2. Douglas-Peucker polyline simplification mk[0] = mk[k-1] = 1; // mark the first and last vertices simplifyDP( _tolerance, &vt[0], 0, k-1, &mk[0] ); // copy marked vertices to the output simplified polyline for (i=m=0; i<k; i++) { if (mk[i]) sV[m++] = vt[i]; } //get rid of the unused points if( m < (int)sV.size() ){ _pts.assign( sV.begin(),sV.begin()+m ); }else{ _pts = sV; } }
void ofPolyline::simplify(float tol){ int n = size(); vector <ofPoint> sV; sV.resize(n); int i, k, m, pv; // misc counters float tol2 = tol * tol; // tolerance squared vector<ofPoint> vt; vector<int> mk; vt.resize(n); mk.resize(n,0); // STAGE 1. Vertex Reduction within tolerance of prior vertex cluster vt[0] = points[0]; // start at the beginning for (i=k=1, pv=0; i<n; i++) { if (d2(points[i], points[pv]) < tol2) continue; vt[k++] = points[i]; pv = i; } if (pv < n-1) vt[k++] = points[n-1]; // finish at the end // STAGE 2. Douglas-Peucker polyline simplification mk[0] = mk[k-1] = 1; // mark the first and last vertices simplifyDP( tol, &vt[0], 0, k-1, &mk[0] ); // copy marked vertices to the output simplified polyline for (i=m=0; i<k; i++) { if (mk[i]) sV[m++] = vt[i]; } //get rid of the unused points if( m < (int)sV.size() ){ points.assign( sV.begin(),sV.begin()+m ); }else{ points = sV; } }
//------------------------------------------------------------------- // needs simplifyDP which is above static vector <ofPoint> ofSimplifyContour(vector <ofPoint> &V, float tol){ int n = V.size(); vector <ofPoint> sV; sV.assign(n, ofPoint()); int i, k, m, pv; // misc counters float tol2 = tol * tol; // tolerance squared ofPoint * vt = new ofPoint[n]; int * mk = new int[n]; memset(mk, 0, sizeof(int) * n ); // STAGE 1. Vertex Reduction within tolerance of prior vertex cluster vt[0] = V[0]; // start at the beginning for (i=k=1, pv=0; i<n; i++) { if (d2(V[i], V[pv]) < tol2) continue; vt[k++] = V[i]; pv = i; } if (pv < n-1) vt[k++] = V[n-1]; // finish at the end // STAGE 2. Douglas-Peucker polyline simplification mk[0] = mk[k-1] = 1; // mark the first and last vertices simplifyDP( tol, vt, 0, k-1, mk ); // copy marked vertices to the output simplified polyline for (i=m=0; i<k; i++) { if (mk[i]) sV[m++] = vt[i]; } //get rid of the unused points if( m < (int)sV.size() ) sV.erase( sV.begin()+m, sV.end() ); delete [] vt; delete [] mk; return sV; }