std::pair< T, T > intersection( const ray<T,2u>& ray, const circle<T>& circle ) { // check for no intersection const T a = dot( ray.direction(), ray.direction() ); const T b = T(2.) * sum( ray.direction() * ( ray.source() - circle.center() ) ); const T c = dot( circle.center(), circle.center() ) + dot( ray.source(), ray.source() ) - T(2.) * dot( ray.source(), circle.center() ) - sqr( circle.radius() ); return solve_quadratic_equation(a,b,c); }
//圆与圆切线 a[],b[],存放对应切线的切点 int gettangentcc(circle c1,circle c2,pt *a,pt *b){ int cnt=0; if (c1.r<c2.r){swap(c1,c2);swap(a,b);} double d2=length(c1.p-c2.p); double rdiff=c1.r-c2.r; double rsum=c1.r+c2.r; if (dcmp(d2-rdiff)<0) return 0;//内含,无切线 double base=atan2(c1.p.y-c2.p.y,c1.p.x-c2.p.x); if (dcmp(d2)==0&&c1.r==c2.r) return -1;//重合 无数条切线 if (dcmp(d2-rdiff)==0){//内切,一条切线 a[cnt]=c1.getpt(base);b[cnt]=c2.getpt(base);cnt++; return 1; } //求外切线 double ang=acos((c1.r-c2.r)/d2); a[cnt]=c1.getpt(base+ang);b[cnt]=c2.getpt(base+ang);cnt++; a[cnt]=c1.getpt(base-ang);b[cnt]=c2.getpt(base-ang);cnt++; if (dcmp(d2-rsum)==0){//两圆外切,一条内切线 a[cnt]=c1.getpt(base);b[cnt]=c2.getpt(pi+base);cnt++; } else if (dcmp(d2-rsum)>0){//两圆相离,两条内切线 ang=acos((c1.r+c2.r)/d2); a[cnt]=c1.getpt(base+ang);b[cnt]=c2.getpt(pi+base+ang);cnt++; a[cnt]=c1.getpt(base-ang);b[cnt]=c2.getpt(pi+base-ang);cnt++; } return cnt; }
//两圆交点 int cinsc(circle c1,circle c2,vector<pt> &sol){ double d=length(c1.p-c2.p); if (dcmp(d)==0){ if (dcmp(c1.r-c2.r)==0) return -1;//重合 return 0;//包含 } if (dcmp(c1.r+c2.r-d)<0) return 0; if (dcmp(fabs(c1.r-c2.r)-d)>0) return 0; double a=atan2(c1.p.y-c2.p.y,c1.p.x-c2.p.x); double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d)); pt p1=c1.getpt(a-da),p2=c1.getpt(a+da); sol.push_back(p1); if (p1==p2) return 1; sol.push_back(p2); return 2; }
std::tuple<bool, float, int> line::intersect(const circle& circle) const { std::tuple<bool, float, int> best = std::make_tuple(false, 0.0f, 0); for(int i = 0; i < 8; ++i) { auto res = std::tuple_cat(intersect(circle.getLineSegment(i)), std::make_tuple(i)); if (std::get<0>(best) == false) { best = res; } else if (std::get<1>(best) > std::get<1>(res)) { best = res; } } return best; }
vector<pair<point, point> > tanCC(const circle &cir1, const circle &cir2) { // `注意: 如果只有三条切线, 即 $s1 = 1, s2 = 1$, 返回的切线可能重复, 切点没有问题` vector<pair<point, point> > list; if (cir1.contain(cir2) || cir2.contain(cir1)) return list; const point &c1 = cir1.o, &c2 = cir2.o; double r1 = cir1.r, r2 = cir2.r; point p, a1, b1, a2, b2; int s1, s2; if (sign(r1 - r2) == 0) { p = c2 - c1; p = (p * (r1 / p.len())).rot90(); list.push_back(make_pair(c1 + p, c2 + p)); list.push_back(make_pair(c1 - p, c2 - p)); } else { p = (c2 * r1 - c1 * r2) / (r1 - r2); s1 = cir1.tanCP(p, a1, b1); s2 = cir2.tanCP(p, a2, b2); if (s1 >= 1 && s2 >= 1) { list.push_back(make_pair(a1, a2)); list.push_back(make_pair(b1, b2)); } } p = (c1 * r2 + c2 * r1) / (r1 + r2); s1 = cir1.tanCP(p, a1, b1); s2 = cir2.tanCP(p, a2, b2); if (s1 >= 1 && s2 >= 1) { list.push_back(make_pair(a1, a2)); list.push_back(make_pair(b1, b2)); } return list; }
void draw_indicator(canvas& cnv, circle cp, float val, color c) { constexpr float w_factor = 0.05; // relative width of the indicator constexpr float h_factor = 0.2; // relative height of the indicator using namespace radial_consts; auto state = cnv.new_state(); auto center = cp.center(); cnv.translate({ center.x, center.y }); cnv.rotate(offset + (val * range)); float r = cp.radius * 0.85; float ind_w = r * w_factor; float ind_h = r * h_factor; rect ind_r = { -ind_w, -ind_h, ind_w, ind_h }; ind_r = ind_r.move(0, r*0.6); draw_indicator(cnv, ind_r, c); }
/* static */ void compact::rotate_branch( iterator it, circle c, double alpha) { assert(!rna_tree::is_leaf(it)); for (pre_post_order_iterator ch = pre_post_order_iterator(it, true); id(ch) <= id(it); ++ch) { if (!ch->inited_points()) continue; double dist = distance(c.centre, ch->at(ch.label_index()).p); c.p1 = ch->at(ch.label_index()).p; c.p2 = move_point(c.centre, c.p2, dist); ch->at(ch.label_index()).p = c.rotate(alpha); } }
void draw_radial_marks(canvas& cnv, circle cp, float size, color c) { using namespace radial_consts; auto state = cnv.new_state(); auto center = cp.center(); constexpr auto num_divs = 50; float div = range / num_divs; auto const& theme = get_theme(); cnv.translate({ center.x, center.y }); cnv.stroke_style(theme.ticks_color); for (int i = 0; i != num_divs+1; ++i) { float from = cp.radius; if (i % (num_divs / 10)) { // Minor ticks from -= size / 4; cnv.line_width(theme.minor_ticks_width); cnv.stroke_style(c.level(theme.minor_ticks_level)); } else { // Major ticks cnv.line_width(theme.major_ticks_width); cnv.stroke_style(c.level(theme.major_ticks_level)); } float angle = offset + (M_PI / 2) + (i * div); float sin_ = std::sin(angle); float cos_ = std::cos(angle); float to = cp.radius - (size / 2); cnv.move_to({ from * cos_, from * sin_ }); cnv.line_to({ to * cos_, to * sin_ }); cnv.stroke(); } }
void draw_radial_labels( canvas& cnv , circle cp , float size , float font_size , std::string const labels[] , std::size_t num_labels ) { if (num_labels < 2) return; // Nothing to do using namespace radial_consts; auto state = cnv.new_state(); auto center = cp.center(); float div = range / (num_labels-1); auto const& theme = get_theme(); cnv.translate({ center.x, center.y }); cnv.text_align(cnv.middle | cnv.center); cnv.fill_style(theme.label_font_color); cnv.font( theme.label_font, theme.label_font_size * font_size, theme.label_style ); for (int i = 0; i != num_labels; ++i) { float angle = offset + (M_PI / 2) + (i * div); float sin_ = std::sin(angle); float cos_ = std::cos(angle); cnv.fill_text({ cp.radius * cos_, cp.radius * sin_ }, labels[i].c_str()); } }
circle::circle(circle &old) { radius = old.getRadius(); color = old.getColor(); circle(radius, color); }
inline bool operator() (const circle &a, const circle &b) { return a.highest(curt) < b.highest(curt); }
double intersect(circle c, point a, point b){ if ( a == c.o || b == c.o ) { // cout << "point same as center" << endl; return 0.0; } if( signum( det(a,b) ) == 0 ) { // cout << "area 0" << endl; return 0.0; } a.x -= c.o.x, a.y -= c.o.y; b.x -= c.o.x , b.y -= c.o.y; c.o = point(); if (c.contains(b)) swap(a, b); if (c.contains(a) && c.contains(b)) { // cout << "sec1 ans : " << 0.5 * fabs(det(a, b)) << endl; return 0.5 * fabs(det(a, b)); // 1. the area of the triangle } if (c.contains(a)) { point p = intersect_cir_line(c, b, a); // cout << "1 pt " << p.x << " " << p.y << endl; //cout << "sec1 ans : " << 0.5 * ( fabs(det(a, p)) + fabs( c.r*c.r * angle(p, b) ) ) << endl; return 0.5 * ( fabs(det(a, p)) + fabs( c.r*c.r * angle(p, b) ) ); // 2. one point inside } if ( point_to(c.o,a, b) >= c.r - EPS){ // cout << "section " << 3 << endl; //cout << "sec3 ans : " << 0.5 * fabs(c.r*c.r * angle(a, b)) << endl; return 0.5 * fabs(c.r*c.r * angle(a, b)); // 3. Both outside and line doesnt intersect } // 4. Both Outside & Line Intersects circle at 2 points point p = intersect_cir_line(c, a, b); point q = intersect_cir_line(c, b, a); point prj = project( point(0,0) , a, b ); double totSector = fabs( c.r * c.r * angle(a,b) ) / 2; double triangle = fabs( det(p,q) ) / 2; double smallSector = fabs( c.r * c.r * angle(p,q) ) / 2; if( onSegment( prj , a, b ) ) { // cout << "sec4 ans: " << totSector - ( smallSector - triangle ) << endl; // cout << "sec4 ans: " << totSector << endl; return totSector - ( smallSector - triangle ) ; } // cout << "2 pts " << " (" << p.x << " " <<p.y << ") (" << q.x << " " << q.y <<")"<< endl; // cout << p.x << " " << p.y << " " << q.x << " " << q.y << endl; // cout << withA.x << " " << withA.y << " " << withB.x << " " << withB.y << endl; // cout << "section " << 4 << endl; // cout << "2 pts " << " (" << p.x << " " <<p.y << ") (" << q.x << " " << q.y <<")"<< endl; // cout << angle(p,q) << endl; // if( p == q ) { //// cout << "here1" << endl; // return 0.5 * fabs(c.r*c.r * angle(a, b)); // } // cout << "here2" << endl; // swap(p,q); // cout << "2 pts " << " (" << p.x << " " <<p.y << ") (" << q.x << " " << q.y <<")"<< endl; // cout << "angles: " << angle( a, p ) << " " << angle(q,b) << endl; //cout << "sec4 ans : " << 0.5 * ( fabs(c.r*c.r*angle(a,p)) + fabs( det(p,q) ) + fabs(c.r*c.r*angle(q,b)) ) << endl; // return 0.5 * ( fabs(c.r*c.r*angle(a,p)) + fabs( det(p,q) ) + fabs(c.r*c.r*angle(q,b)) ); // seems fine // double totSector = fabs( c.r * c.r * angle(a,b) ) / 2; // double triangle = fabs( det(p,q) ) / 2; // double smallSector = fabs( c.r * c.r * angle(p,q) ) / 2; //// cout << "sec4 ans: " << totSector - ( smallSector - triangle ) << endl; // cout << "sec4 ans: " << totSector << endl; return totSector ; }
// Area template<class T> inline pure T area(const circle<T>& a) { return M_PI * std::sqr(a.r()); }