point_t incenter(const point_t& a, const point_t& b, const point_t& c) { point_t p1 = b - a, p2 = c - a; std::swap(p1.x, p1.y); std::swap(p2.x, p2.y); p1.x = -p1.x, p2.x = -p2.x; point_t m1 = middle_point(a, b); point_t m2 = middle_point(a, c); double k = (m2 - m1) * p2 / (p1 * p2); return point_t(k * p1.x, k * p1.y) + m1; }
/* 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; }
bool solve() { int N; std::scanf("%d", &N); if(N == 0) return false; for(int i = 0; i != N; ++i) std::scanf("%lf %lf", &pt[i].x, &pt[i].y); std::random_shuffle(pt, pt + N); point_t c = pt[0]; double r = 0.0; for(int i = 1; i != N; ++i) { if(dist(pt[i], c) <= r + eps) continue; c = pt[i], r = 0.0; for(int j = 0; j != i; ++j) { if(dist(pt[j], c) <= r + eps) continue; c = middle_point(pt[i], pt[j]); r = dist(c, pt[i]); for(int k = 0; k != j; ++k) { if(dist(pt[k], c) <= r + eps) continue; c = incenter(pt[i], pt[j], pt[k]); r = dist(c, pt[i]); } } } std::printf("%.2lf %.2lf %.2lf\n", c.x, c.y, std::sqrt(r)); return true; }
/* 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; }
void CheckBox::PaintBox(Canvas& canvas, const Rect& box_rect) const { //Paint the box. canvas.SetBrushWithColor(GetBoxBackgroundColor()); canvas.DrawRectangle(box_rect); canvas.SetBrushWithColor(GetBoxBorderColor()); canvas.DrawRectangleFrame(box_rect, 1); //Paint the check state mark. auto check_state = GetCheckState(); if (check_state == CheckState::Indeterminate) { Rect mark_rect = box_rect; mark_rect.Inflate(-3); canvas.DrawRectangle(mark_rect); } else if (check_state == CheckState::Checked) { auto path = GetResourceFactory()->CreatePathGeometry(); if (path == nullptr) { return; } auto sink = path->Open(); if (sink == nullptr) { return; } Rect mark_rect = box_rect; mark_rect.Inflate(-2); Point start_point(mark_rect.position.x + mark_rect.size.width, mark_rect.position.y); Point middle_point(mark_rect.position.x + mark_rect.size.width * 0.4f, mark_rect.position.y + mark_rect.size.height - 1); Point end_point(mark_rect.position.x, mark_rect.position.y + mark_rect.size.height * 0.4f); sink->BeginFigure(start_point, GeometrySink::BeginFigureOption::Hollow); sink->AddLine(middle_point); sink->AddLine(end_point); sink->EndFigure(GeometrySink::EndFigureOption::Open); sink->Close(); canvas.DrawGeometryFrame(path, 1.5); } }
/* * NOTE: this implementation follows Standard SVG 1.1 implementation guidelines * for elliptical arc curves. See Appendix F.6. */ void EllipticalArc::_updateCenterAndAngles(bool svg) { Point d = initialPoint() - finalPoint(); // TODO move this to SVGElipticalArc? if (svg) { if ( initialPoint() == finalPoint() ) { _rot_angle = _start_angle = _end_angle = 0; _center = initialPoint(); _rays = Geom::Point(0,0); _large_arc = _sweep = false; return; } _rays[X] = std::fabs(_rays[X]); _rays[Y] = std::fabs(_rays[Y]); if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) { _rays[X] = L2(d) / 2; _rays[Y] = 0; _rot_angle = std::atan2(d[Y], d[X]); _start_angle = 0; _end_angle = M_PI; _center = middle_point(initialPoint(), finalPoint()); _large_arc = false; _sweep = false; return; } } else { if ( are_near(initialPoint(), finalPoint()) ) { if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) { _start_angle = _end_angle = 0; _center = initialPoint(); return; } else { THROW_RANGEERROR("initial and final point are the same"); } } if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) { // but initialPoint != finalPoint THROW_RANGEERROR( "there is no ellipse that satisfies the given constraints: " "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint" ); } if ( are_near(ray(Y), 0) ) { Point v = initialPoint() - finalPoint(); if ( are_near(L2sq(v), 4*ray(X)*ray(X)) ) { Angle angle(v); if ( are_near( angle, _rot_angle ) ) { _start_angle = 0; _end_angle = M_PI; _center = v/2 + finalPoint(); return; } angle -= M_PI; if ( are_near( angle, _rot_angle ) ) { _start_angle = M_PI; _end_angle = 0; _center = v/2 + finalPoint(); return; } THROW_RANGEERROR( "there is no ellipse that satisfies the given constraints: " "ray(Y) == 0 " "and slope(initialPoint - finalPoint) != rotation_angle " "and != rotation_angle + PI" ); } if ( L2sq(v) > 4*ray(X)*ray(X) ) { THROW_RANGEERROR( "there is no ellipse that satisfies the given constraints: " "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)" ); } else { THROW_RANGEERROR( "there is infinite ellipses that satisfy the given constraints: " "ray(Y) == 0 and distance(initialPoint, finalPoint) < 2*ray(X)" ); } } if ( are_near(ray(X), 0) ) { Point v = initialPoint() - finalPoint(); if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) ) { double angle = std::atan2(v[Y], v[X]); if (angle < 0) angle += 2*M_PI; double rot_angle = _rot_angle.radians() + M_PI/2; if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI; if ( are_near( angle, rot_angle ) ) { _start_angle = M_PI/2; _end_angle = 3*M_PI/2; _center = v/2 + finalPoint(); return; } angle -= M_PI; if ( angle < 0 ) angle += 2*M_PI; if ( are_near( angle, rot_angle ) ) { _start_angle = 3*M_PI/2; _end_angle = M_PI/2; _center = v/2 + finalPoint(); return; } THROW_RANGEERROR( "there is no ellipse that satisfies the given constraints: " "ray(X) == 0 " "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 " "and != rotation_angle + (3/2)*PI" ); } if ( L2sq(v) > 4*ray(Y)*ray(Y) ) { THROW_RANGEERROR( "there is no ellipse that satisfies the given constraints: " "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)" ); } else { THROW_RANGEERROR( "there is infinite ellipses that satisfy the given constraints: " "ray(X) == 0 and distance(initialPoint, finalPoint) < 2*ray(Y)" ); } } } Rotate rm(_rot_angle); Affine m(rm); m[1] = -m[1]; m[2] = -m[2]; Point p = (d / 2) * m; double rx2 = _rays[X] * _rays[X]; double ry2 = _rays[Y] * _rays[Y]; double rxpy = _rays[X] * p[Y]; double rypx = _rays[Y] * p[X]; double rx2py2 = rxpy * rxpy; double ry2px2 = rypx * rypx; double num = rx2 * ry2; double den = rx2py2 + ry2px2; assert(den != 0); double rad = num / den; Point c(0,0); if (rad > 1) { rad -= 1; rad = std::sqrt(rad); if (_large_arc == _sweep) rad = -rad; c = rad * Point(rxpy / ray(Y), -rypx / ray(X)); _center = c * rm + middle_point(initialPoint(), finalPoint()); } else if (rad == 1 || svg) { double lamda = std::sqrt(1 / rad); _rays[X] *= lamda; _rays[Y] *= lamda; _center = middle_point(initialPoint(), finalPoint()); } else { THROW_RANGEERROR( "there is no ellipse that satisfies the given constraints" ); } Point sp((p[X] - c[X]) / ray(X), (p[Y] - c[Y]) / ray(Y)); Point ep((-p[X] - c[X]) / ray(X), (-p[Y] - c[Y]) / ray(Y)); Point v(1, 0); _start_angle = angle_between(v, sp); double sweep_angle = angle_between(sp, ep); if (!_sweep && sweep_angle > 0) sweep_angle -= 2*M_PI; if (_sweep && sweep_angle < 0) sweep_angle += 2*M_PI; _end_angle = _start_angle; _end_angle += sweep_angle; }