我创建了一个程序,根据黑/白位图将鼠标限制在某个区域.该程序按原样100%运行,但是当它偏离区域外时,使用不准确但尽管快速的算法来重新定位鼠标.
目前,当鼠标移动到该区域之外时,基本上会发生以下情况:
>在区域内的预定义静态点和鼠标的新位置之间绘制一条线.
>找到该线与允许区域边缘相交的点.
>鼠标移动到该点.
这可以工作,但只适用于完美的圆形,其中预定义的点设置在精确的中心.不幸的是,情况永远不会如此.该应用将与各种矩形和不规则的无定形形状一起使用.在这样的形状上,绘制的线与边缘相交的点通常不是鼠标形状上的最近点.
我需要创建一个新算法,找到鼠标在允许区域边缘的新位置的最近点.我怎样才能做到这一点?优选地,该方法应该能够足够快地执行以在将鼠标拖动到该区域的边缘时给予平滑的鼠标移动.
(我在OS X 10.7上的Objective C / Cocoa中执行此操作,但是,如果您不想输入代码或不知道Objective C/C++,则伪代码很好)
谢谢!
这是我目前的算法:
#import <Cocoa/Cocoa.h> #import "stuff.h" #import <CoreMedia/CoreMedia.h> bool is_in_area(NSInteger x,NSInteger y,NSBitmapImageRep *mouse_mask){ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSUInteger pixel[4]; [mouse_mask getPixel:pixel atX:x y:y]; if(pixel[0]!= 0){ [pool release]; return false; } [pool release]; return true; } CGEventRef mouse_filter(CGEventTapProxy proxy,CGEventType type,CGEventRef event,NSBitmapImageRep *mouse_mask) { CGPoint point = CGEventGetLocation(event); float tX = point.x; float tY = point.y; if( is_in_area(tX,tY,mouse_mask)){ // target is inside O.K. area,do nothing }else{ CGPoint target; //point inside restricted region: float iX = 600; // inside x float iY = 500; // inside y // delta to midpoint between iX,iY and tX,tY float dX; float dY; float accuracy = .5; //accuracy to loop until reached do { dX = (tX-iX)/2; dY = (tY-iY)/2; if(is_in_area((tX-dX),(tY-dY),mouse_mask)){ iX += dX; iY += dY; } else { tX -= dX; tY -= dY; } } while (abs(dX)>accuracy || abs(dY)>accuracy); target = CGPointMake(roundf(tX),roundf(tY)); CGDisplayMoveCursorToPoint(CGMainDisplayID(),target); } return event; } int main(int argc,char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; stuff *stuff_doer = [[stuff alloc] init]; NSBitmapImageRep *mouse_mask= [stuff_doer get_mouse_mask]; CFRunLoopSourceRef runLoopSource; CGEventMask event_mask; event_mask = CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged) | CGEventMaskBit(kCGEventOtherMouseDragged); CGSetLocalEventsSuppressionInterval(0); CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,event_mask,mouse_filter,mouse_mask); if (!eventTap) { NSLog(@"Couldn't create event tap!"); exit(1); } runLoopSource = CFMachPortCreateRunLoopSource(kcfAllocatorDefault,eventTap,0); CFRunLoopAddSource(CFRunLoopGetCurrent(),runLoopSource,kcfRunLoopCommonModes); CGEventTapEnable(eventTap,true); CFRunLoopRun(); CFRelease(eventTap); CFRelease(runLoopSource); [pool release]; exit(0); }
这是可能使用的区域位图的示例,黑色是允许的区域.
这表明为什么转换为多边形不方便或者甚至不合理.