【问题标题】:Drawing along the edge of a ruler object沿标尺对象的边缘绘制
【发布时间】: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


【解决方案1】:

Josh Caswell 的评论给了我一个想法。在this 文章中,表示children中的坐标存储在本地空间中。我以前知道这一点,但不知何故,这意味着无论您如何旋转视图,视图始终朝上。它仅根据其在世界空间(或父空间)中的坐标进行旋转。

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

【讨论】:

    猜你喜欢
    • 2020-06-24
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    • 2018-06-08
    相关资源
    最近更新 更多