2012-07-18 36 views
3

我接近解决这个问题,但有一个部分给我带来麻烦。我试图模仿一个标尺对象,用户可以旋转,缩放并放置在画布上,然后沿着边缘追踪以在画布上标记。我遇到的问题是无论用户的手指在哪里,都会获得下一个点。我可以追溯法线从点回到沿着我有的边缘的一个小的透明视图,但由于锯齿(或某物)线抽搐,因为它在任何角度而不是纯直线(0,90,180) ,270)。我也试着编写一个像CGRectContainsPoint这样的函数,除了它需要一个任意旋转的矩形,但我没有成功。沿着标尺物体的边缘绘图

这里是计算基于用户的触摸点的代码:因为不管是什么原因

- (CGPoint)perpendicularPointFromPoint:(CGPoint)point 
{ 
    CGPoint testPoint1 = point; 
    CGPoint testPoint2 = testPoint1; 
    CGPoint pointToUse = CGPointZero; 

    //Get the right angle to the current rotation, and make 
    //a unit vector in that direction 
    CGFloat rightAngle = mCurRotation + M_PI_2; 
    CGFloat xInc = cosf(rightAngle); 
    CGFloat yInc = sinf(rightAngle); 

    //Check both "forward" and "backward" 
    int counter = 0; 
    while(pointToUse.x == 0) 
    { 
     testPoint1.x += xInc; 
     testPoint1.y += yInc; 
     testPoint2.x -= xInc; 
     testPoint2.y -= yInc; 

     //mLineOutline is a small view on top of the ruler (transparent) 
     if([self.superview hitTest:testPoint1 withEvent:nil] == mLineOutline) 
     { 
      pointToUse = testPoint1; 
     } 
     else if([self.superview hitTest:testPoint2 withEvent:nil] == mLineOutline) 
     { 
      pointToUse = testPoint2; 
     } 
     else if(counter++ > 1000) //Neither ray intersects the ruler 
      pointToUse.x = -1.f; 
    } 

    return CGPointMake(roundf(pointToUse.x), roundf(pointToUse.y)); 
} 

然而,行不安,因为我画它(只有几个像素上下,但很明显)。我能做些什么来解决这个问题?另外,有没有一个尴尬的方式?

+0

这个想法是,胖手指的用户的绘图被“折断”到标尺的边缘,这样手指的移动刚刚结束,表示绘制线的长度?你得到的“抽搐”是长度_?或者从标尺上垂直/远离? – 2012-07-18 05:11:11

+0

@JoshCaswell当你画画的时候,你可以在尺子上看到小点(1厘米,2厘米),并且即使你的手指不稳定也可以有一条直线。尽管如此,你的总结也相当准确。您可以尽可能远地移动手指并看到您正在绘制的线条。线垂直于标尺,抽搐的长度非常平滑。我知道这与半像素和命中测试有关。 – borrrden 2012-07-18 05:21:22

+0

'mLineOutline'旋转,以便其边缘与尺子相同?我不太确定如何检查,但你确定superview用于命中测试的矩形与旋转视图的矩形相同吗?考虑到最小的_non-rotated_包围矩形(即帧/边界区分突然变得重要),我记得视图指南中关于超视图的一些东西。让我看看我是否可以找到它... – 2012-07-18 05:31:45

回答

3

乔希卡斯韦尔的评论给了我一个主意。在this文章中,它表示儿童坐标存储在本地空间中。我之前就知道这一点,但不知何故,这意味着无论你如何旋转它,这都意味着视图总是面临着问题。它只是根据其在世界空间(或父空间)中的坐标旋转。

因此,不是在超视图上获取触摸点然后计算,而是在子视图上获取触摸点。将它的y值更改为-2或任何我想要的(就在标尺上方,因为它总是面向本地空间),然后[self convertPoint:point toView:self.superview];让视图层次结构负责处理难度较高的部分。