BOOL LLJoystick::handleMouseDown(S32 x, S32 y, MASK mask) { //llinfos << "joystick mouse down " << x << ", " << y << llendl; bool handles = false; if(pointInCircle(x, y)) { mLastMouse.set(x, y); mFirstMouse.set(x, y); mMouseDownTimer.reset(); handles = LLButton::handleMouseDown(x, y, mask); } return handles; }
static int findEnslosingCicle4pts_32f( Point2f* pts, Point2f& _center, float& _radius ) { int shuffles[4][4] = { {0, 1, 2, 3}, {0, 1, 3, 2}, {2, 3, 0, 1}, {2, 3, 1, 0} }; int idxs[4] = { 0, 1, 2, 3 }; int i, j, k = 1, mi = 0; float max_dist = 0; Point2f center; Point2f min_center; float radius, min_radius = FLT_MAX; Point2f res_pts[4]; center = min_center = pts[0]; radius = 1.f; for( i = 0; i < 4; i++ ) for( j = i + 1; j < 4; j++ ) { float dist = (float)norm(pts[i] - pts[j]); if( max_dist < dist ) { max_dist = dist; idxs[0] = i; idxs[1] = j; } } if( max_dist > 0 ) { k = 2; for( i = 0; i < 4; i++ ) { for( j = 0; j < k; j++ ) if( i == idxs[j] ) break; if( j == k ) idxs[k++] = i; } center = Point2f( (pts[idxs[0]].x + pts[idxs[1]].x)*0.5f, (pts[idxs[0]].y + pts[idxs[1]].y)*0.5f ); radius = (float)(norm(pts[idxs[0]] - center)*1.03); if( radius < 1.f ) radius = 1.f; if( pointInCircle( pts[idxs[2]], center, radius ) >= 0 && pointInCircle( pts[idxs[3]], center, radius ) >= 0 ) { k = 2; //rand()%2+2; } else { mi = -1; for( i = 0; i < 4; i++ ) { if( findCircle( pts[shuffles[i][0]], pts[shuffles[i][1]], pts[shuffles[i][2]], ¢er, &radius ) ) { radius *= 1.03f; if( radius < 2.f ) radius = 2.f; if( pointInCircle( pts[shuffles[i][3]], center, radius ) >= 0 && min_radius > radius ) { min_radius = radius; min_center = center; mi = i; } } } CV_Assert( mi >= 0 ); if( mi < 0 ) mi = 0; k = 3; center = min_center; radius = min_radius; for( i = 0; i < 4; i++ ) idxs[i] = shuffles[mi][i]; } } _center = center; _radius = radius; /* reorder output points */ for( i = 0; i < 4; i++ ) res_pts[i] = pts[idxs[i]]; for( i = 0; i < 4; i++ ) { pts[i] = res_pts[i]; CV_Assert( pointInCircle( pts[i], center, radius ) >= 0 ); } return k; }
void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radius ) { int max_iters = 100; const float eps = FLT_EPSILON*2; bool result = false; Mat points = _points.getMat(); int i, j, k, count = points.checkVector(2); int depth = points.depth(); Point2f center; float radius = 0.f; CV_Assert(count >= 0 && (depth == CV_32F || depth == CV_32S)); _center.x = _center.y = 0.f; _radius = 0.f; if( count == 0 ) return; bool is_float = depth == CV_32F; const Point* ptsi = (const Point*)points.data; const Point2f* ptsf = (const Point2f*)points.data; Point2f pt = is_float ? ptsf[0] : Point2f((float)ptsi[0].x,(float)ptsi[0].y); Point2f pts[4] = {pt, pt, pt, pt}; for( i = 1; i < count; i++ ) { pt = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y); if( pt.x < pts[0].x ) pts[0] = pt; if( pt.x > pts[1].x ) pts[1] = pt; if( pt.y < pts[2].y ) pts[2] = pt; if( pt.y > pts[3].y ) pts[3] = pt; } for( k = 0; k < max_iters; k++ ) { double min_delta = 0, delta; Point2f farAway(0,0); /*only for first iteration because the alg is repared at the loop's foot*/ if( k == 0 ) findEnslosingCicle4pts_32f( pts, center, radius ); for( i = 0; i < count; i++ ) { pt = is_float ? ptsf[i] : Point2f((float)ptsi[i].x,(float)ptsi[i].y); delta = pointInCircle( pt, center, radius ); if( delta < min_delta ) { min_delta = delta; farAway = pt; } } result = min_delta >= 0; if( result ) break; Point2f ptsCopy[4]; // find good replacement partner for the point which is at most far away, // starting with the one that lays in the actual circle (i=3) for( i = 3; i >= 0; i-- ) { for( j = 0; j < 4; j++ ) ptsCopy[j] = i != j ? pts[j] : farAway; findEnslosingCicle4pts_32f( ptsCopy, center, radius ); if( pointInCircle( pts[i], center, radius ) >= 0) { // replaced one again in the new circle? pts[i] = farAway; break; } } } if( !result ) { radius = 0.f; for( i = 0; i < count; i++ ) { pt = is_float ? ptsf[i] : Point2f((float)ptsi[i].x,(float)ptsi[i].y); float dx = center.x - pt.x, dy = center.y - pt.y; float t = dx*dx + dy*dy; radius = MAX(radius, t); } radius = (float)(std::sqrt(radius)*(1 + eps)); } _center = center; _radius = radius; }