/* summarized distance centroid */ void label_position3(double *x, double *y) const { if (type_ == LineString || type_ == MultiLineString) { middle_point(x,y); return; } unsigned i = 0; double l = 0.0; double tl = 0.0; double cx = 0.0; double cy = 0.0; double x0 = 0.0; double y0 = 0.0; double x1 = 0.0; double y1 = 0.0; unsigned size = cont_.size(); for (i = 0; i < size-1; i++) { cont_.get_vertex(i,&x0,&y0); cont_.get_vertex(i+1,&x1,&y1); l = distance(x0,y0,x1,y1); cx += l * (x1 + x0)/2; cy += l * (y1 + y0)/2; tl += l; } *x = cx / tl; *y = cy / tl; }
/* center of gravity centroid - best visually but does not work with multipolygons */ void label_position(double *x, double *y) const { if (type_ == LineString || type_ == MultiLineString) { middle_point(x,y); return; } unsigned size = cont_.size(); if (size < 3) { cont_.get_vertex(0,x,y); return; } double ai; double atmp = 0; double xtmp = 0; double ytmp = 0; double x0 =0; double y0 =0; double x1 =0; double y1 =0; double ox =0; double oy =0; unsigned i; // Use first point as origin to improve numerical accuracy cont_.get_vertex(0,&ox,&oy); for (i = 0; i < size-1; i++) { cont_.get_vertex(i,&x0,&y0); cont_.get_vertex(i+1,&x1,&y1); x0 -= ox; y0 -= oy; x1 -= ox; y1 -= oy; ai = x0 * y1 - x1 * y0; atmp += ai; xtmp += (x1 + x0) * ai; ytmp += (y1 + y0) * ai; } if (atmp != 0) { *x = (xtmp/(3*atmp)) + ox; *y = (ytmp/(3*atmp)) + oy; return; } *x=x0; *y=y0; }
bool hit_test(value_type x, value_type y, double tol) const { if (cont_.size() == 1) { // Handle points double x0, y0; cont_.get_vertex(0, &x0, &y0); return distance(x, y, x0, y0) <= fabs(tol); } else if (cont_.size() > 1) { bool inside=false; double x0=0; double y0=0; rewind(0); vertex(&x0, &y0); unsigned command; double x1,y1; while (SEG_END != (command=vertex(&x1, &y1))) { if (command == SEG_MOVETO) { x0 = x1; y0 = y1; continue; } if ((((y1 <= y) && (y < y0)) || ((y0 <= y) && (y < y1))) && ( x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1)) inside=!inside; x0=x1; y0=y1; } return inside; } return false; }
void middle_point(double *x, double *y) const { // calculate mid point on path double x0=0; double y0=0; double x1=0; double y1=0; unsigned size = cont_.size(); if (size == 1) { cont_.get_vertex(0,x,y); } else if (size == 2) { cont_.get_vertex(0,&x0,&y0); cont_.get_vertex(1,&x1,&y1); *x = 0.5 * (x1 + x0); *y = 0.5 * (y1 + y0); } else { double len=0.0; for (unsigned pos = 1; pos < size; ++pos) { cont_.get_vertex(pos-1,&x0,&y0); cont_.get_vertex(pos,&x1,&y1); double dx = x1 - x0; double dy = y1 - y0; len += std::sqrt(dx * dx + dy * dy); } double midlen = 0.5 * len; double dist = 0.0; for (unsigned pos = 1; pos < size;++pos) { cont_.get_vertex(pos-1,&x0,&y0); cont_.get_vertex(pos,&x1,&y1); double dx = x1 - x0; double dy = y1 - y0; double seg_len = std::sqrt(dx * dx + dy * dy); if (( dist + seg_len) >= midlen) { double r = (midlen - dist)/seg_len; *x = x0 + (x1 - x0) * r; *y = y0 + (y1 - y0) * r; break; } dist += seg_len; } } }
unsigned get_vertex(unsigned pos, double* x, double* y) const { return cont_.get_vertex(pos, x, y); }
unsigned vertex(double* x, double* y) const { return cont_.get_vertex(itr_++,x,y); }
unsigned vertex(std::size_t index, double* x, double* y) const { return cont_.get_vertex(index, x, y); }