【发布时间】:2012-07-18 04:45:30
【问题描述】:
我即将解决这个问题,但有一部分给我带来了麻烦。我试图模仿一个标尺对象,用户可以在画布上旋转、缩放和放置它,然后沿着边缘追踪以在画布上做一个标记。我遇到的问题是无论用户的手指走到哪里,都可以在线获得下一个点。我可以将法线从该点追溯到我所拥有的边缘的一个小的透明视图,但是由于混叠(或其他原因),线在以纯直线以外的任何角度(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));
}
但是,由于某种原因,线条在我绘制时会抖动(上下只有几个像素,但非常明显)。我能做些什么来对抗这个?还有,有没有不那么尴尬的方法?
【问题讨论】:
-
这个想法是胖手指用户的绘图被“捕捉”到标尺的边缘,因此手指移动最终只是指示绘制线的长度?你得到的“抽搐”是沿着那个长度?还是垂直/远离标尺?
-
@JoshCaswell 这真的是让您在绘图时可以看到标尺上的小点(1 厘米、2 厘米),即使手指不稳也能画出一条直线。你的总结也很准确。您可以随意移动手指并查看您正在绘制的线条。线条垂直于尺子抽动,长度非常平滑。我知道这与半像素和命中测试有关。
-
而
mLineOutline被旋转,使其边缘与标尺相同?我不太确定如何检查这一点,但是您确定超级视图用于命中测试的矩形与旋转视图的矩形相同吗?我记得视图指南中关于超级视图的一些内容,考虑到最小的 非旋转 封闭矩形(即,框架/边界的区别突然变得很重要)。让我看看能不能找到…… -
这部分的底部"Converting Coordinates in the View Hierarchy"是我想到的,但我不知道从那里去哪里。
-
@JoshCaswell
mLineOutline是标尺的子视图,如果我为其分配颜色背景,我可以看到它随着标尺移动。这条线总体是正确的,只是在改变长度时有一些小的波动。该链接中的图形给了我一个想法。
标签: objective-c ios algorithm trigonometry