objective-c – 如何确定某个形状上鼠标的最近点?

前端之家收集整理的这篇文章主要介绍了objective-c – 如何确定某个形状上鼠标的最近点?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我创建了一个程序,根据黑/白位图将鼠标限制在某个区域.该程序按原样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);
}

这是可能使用的区域位图的示例,黑色是允许的区域.
这表明为什么转换为多边形不方便或者甚至不合理.

解决方法

一些想法:

>对形式问题采用非常标准的方法:“给定一组2D点S(在您的情况下,边缘点集合)和查询点P(在您的情况下,鼠标位置),找到最接近的点P in中的S,是使用四叉树.它们可以看作二维搜索到2D的概括. Quadtrees是电子游戏中碰撞检测的热门,所以你可以在谷歌找到很多教程.>形状是变化还是静止?在第二种情况下,如果内存不是问题,我只需预先计算每个像素的最近边缘点并将其放入查找表中. (实际上,我只使用两个数组,一个用于x坐标,另一个用于y坐标).通过使用Floyd-Warshall算法的某些东西可以消除冗余计算,在这种情况下,这种算法具有非常简单的形式.

猜你在找的cocoa相关文章