dLine Conv::line_bck(const dLine & l, double acc, int max) const { dLine ret; if (l.size()==0) return ret; dPoint P1 = l[0], P1a =P1; bck(P1a); ret.push_back(P1a); dPoint P2, P2a; for (int i=1; i<l.size(); i++){ P1 = l[i-1]; P2 = l[i]; double d = pdist(P1-P2)/(max+1)*1.5; do { P1a = P1; bck(P1a); P2a = P2; bck(P2a); dPoint C1 = (P1+P2)/2.; dPoint C1a = C1; bck(C1a); if ((pdist(C1a, (P1a+P2a)/2.) < acc) || (pdist(P1-P2) < d)){ ret.push_back(P2a); P1 = P2; P2 = l[i]; } else { P2 = C1; } } while (P1!=P2); } return ret; }
g_map mk_tmerc_ref(const dLine & points, double u_per_m, bool yswap){ g_map ref; if (points.size()<3){ cerr << "error in mk_tmerc_ref: number of points < 3\n"; return g_map(); } // Get refs. // Reduce border to 5 points, remove last one. dLine refs = points; refs.push_back(*refs.begin()); // to assure last=first refs = generalize(refs, -1, 5); refs.resize(4); // Create tmerc->lonlat tmerc conversion with wanted lon0, // convert refs to our map coordinates. Options PrO; PrO.put<double>("lon0", convs::lon2lon0(points.center().x)); convs::pt2wgs cnv(Datum("wgs84"), Proj("tmerc"), PrO); dLine refs_c(refs); cnv.line_bck_p2p(refs_c); refs_c *= u_per_m; // to out units refs_c -= refs_c.range().TLC(); double h = refs_c.range().h; // swap y if needed if (yswap){ for (int i=0;i<refs_c.size();i++) refs_c[i].y = h - refs_c[i].y; } // add refpoints to our map for (int i=0;i<refs.size();i++){ ref.push_back(g_refpoint(refs[i], refs_c[i])); } ref.map_proj=Proj("tmerc"); ref.proj_opts.put("lon0", convs::lon2lon0(refs.range().CNT().x)); // Now we need to convert border to map units. // We can convert them by the same way as refs, but // this is unnecessary duplicating of non-trivial code. // So we constract map2pt conversion from our map. // Set map border convs::map2wgs brd_cnv(ref); ref.border = brd_cnv.line_bck(points); ref.border.push_back(*ref.border.begin()); // to assure last=first ref.border = generalize(ref.border, 1000, -1); // 1 unit accuracy ref.border.resize(ref.border.size()-1); return ref; }
dLine Conv::line_frw(const dLine & l, double acc, int max) const { dLine ret; if (l.size()==0) return ret; dPoint P1 = l[0], P1a =P1; frw(P1a); ret.push_back(P1a); // add first point dPoint P2, P2a; for (int i=1; i<l.size(); i++){ P1 = l[i-1]; P2 = l[i]; double d = pdist(P1-P2)/(max+1)*1.5; do { P1a = P1; frw(P1a); P2a = P2; frw(P2a); // C1 - is a center of (P1-P2) // C2-C1 is a perpendicular to (P1-P2) with acc length dPoint C1 = (P1+P2)/2.; dPoint C2 = C1 + acc*pnorm(dPoint(P1.y-P2.y, -P1.x+P2.x)); dPoint C1a = C1; frw(C1a); dPoint C2a = C2; frw(C2a); if ((pdist(C1a, (P1a+P2a)/2.) < pdist(C1a,C2a)) || (pdist(P1-P2) < d)){ // go to the rest of line (P2-l[i]) ret.push_back(P2a); P1 = P2; P2 = l[i]; } else { // go to the first half (P1-C1) of current line P2 = C1; } } while (P1!=P2); } return ret; }
void fig_object::set_points(const dLine & v){ clear(); for (int i=0;i<v.size();i++) push_back(iPoint(lround(v[i].x), lround(v[i].y))); }