为用户创建的给定行创建行扩展

时间:2015-08-02 18:28:08

标签: ios math drawing core-graphics line

我一直在使用应用程序,我必须抓住用户的触摸并在屏幕上画一条线。到目前为止这是有效的。

current implementation

问题在于我想为从行开始/结束到屏幕边界的那条线创建某种扩展。对于该扩展,重要的是与主线对齐。

expected implementation

我已经尝试了几天,但没有取得积极成果。我的想法是使用某种线性方程来表示线,然后在线上和屏幕边界上创建两个点。我遇到的第一个问题是垂直线。

y = m * x + b
slope = (y2 - y2)/(x2 - x1)
y_intercept = b = y - m * x

用户还可以在任何方向和方向创建线条。 problem 1/3

我试图用这些方程找到任意点(x = 0,y = 0,x = 320,y = 480),但我得到了一些奇怪的问题,如下图所示。

a)线条进一步超越了屏幕的极限。这导致应用程序几乎崩溃。 problem 2/3

b)此外,我无法确定如何将每个新点与当前触摸点相关联。 problem 3/3

代码

import Foundation
import UIKit





public class TestView : UIView
{
    var lineLayer : CAShapeLayer?
    var lineExtensionALayer : CAShapeLayer?
    var lineExtensionBLayer : CAShapeLayer?

    var startPoint : CGPoint?
    var endPoint : CGPoint?

    override init(frame: CGRect){
        super.init(frame:frame)

        self.backgroundColor = UIColor.clearColor()

        self.lineLayer = self.createLine(color: UIColor.redColor())
        self.lineExtensionALayer = self.createLine(color: UIColor.greenColor())
        self.lineExtensionBLayer = self.createLine(color: UIColor.blueColor())
    }

    required public init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    public override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        let touch : UITouch = touches.first as! UITouch
        let position = touch.locationInView(self)

        self.startPoint = position
    }

    public override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {

    }

    public override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {

    }

    public override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {

        let touch : UITouch = touches.first as! UITouch
        let position = touch.locationInView(self)

        self.endPoint = position

        self.updateLine()
    }


    func createLine(color selectedColor : UIColor) -> CAShapeLayer
    {
        let line = CAShapeLayer()
        line.frame = self.bounds
        line.strokeColor = selectedColor.CGColor
        line.fillColor = nil
        line.lineWidth = 2

        self.layer.addSublayer(line)

        return line
    }

    func drawLine(line lineToDraw : CAShapeLayer,start pointA : CGPoint, end pointB : CGPoint)
    {
        let path = UIBezierPath()
        path.moveToPoint(pointA)
        path.addLineToPoint(pointB)

        lineToDraw.path = path.CGPath
    }

    func updateLine(){

        var line = LineFunction(point1: self.startPoint!, point2: self.endPoint!)

        // Draw main line.
        self.drawLine(line: self.lineLayer!, start: self.startPoint!, end: self.endPoint!)
    }
}

1 个答案:

答案 0 :(得分:1)

取自this answer,翻译成swift并稍作改动:

func getLines(xmin: CGFloat, ymin: CGFloat, xmax: CGFloat, ymax: CGFloat, x1: CGFloat, x2: CGFloat, y1: CGFloat, y2: CGFloat) -> (CGPoint, CGPoint) {
    if y1 == y2 {
        return (CGPoint(x: xmin, y: y1), CGPoint(x: xmax, y: y1))
    }
    if x1 == x2 {
        return (CGPoint(x: x1, y: ymin), CGPoint(x: x1, y: ymax))
    }

    let y_for_xmin = y1 + (y2 - y1) * (xmin - x1) / (x2 - x1)
    let y_for_xmax = y1 + (y2 - y1) * (xmax - x1) / (x2 - x1)

    let x_for_ymin = x1 + (x2 - x1) * (ymin - y1) / (y2 - y1)
    let x_for_ymax = x1 + (x2 - x1) * (ymax - y1) / (y2 - y1)

    if ymin <= y_for_xmin && y_for_xmin <= ymax {
        if xmin <= x_for_ymax && x_for_ymax <= xmax {
            return (CGPoint(x: xmin, y: y_for_xmin), CGPoint(x: x_for_ymax, y: ymax))
        }
        if xmin <= x_for_ymin && x_for_ymin <= xmax {
            return (CGPoint(x: xmin, y: y_for_xmin), CGPoint(x: x_for_ymin, y: ymin))
        }
        return (CGPoint(x: xmin, y: y_for_xmin), CGPoint(x: xmax, y: y_for_xmax))
    }

    if ymin <= y_for_xmax && y_for_xmax <= ymax {
        if xmin <= x_for_ymin && x_for_ymin <= xmax {
            return (CGPoint(x: x_for_ymin, y: ymin), CGPoint(x: xmax, y: y_for_xmax))
        }
        if xmin <= x_for_ymax && x_for_ymax <= xmax {
            return (CGPoint(x: x_for_ymax, y: ymax), CGPoint(x: xmax, y: y_for_xmax))
        }
        return (CGPoint(x: xmin, y: y_for_xmin), CGPoint(x: xmax, y: y_for_xmax))
    }

    return (CGPoint(x: x_for_ymin, y: ymin), CGPoint(x: x_for_ymax, y: ymax))
}

func updateLine(){
    let x1 = self.startPoint!.x
    let x2 = self.endPoint!.x
    let y1 = self.startPoint!.y
    let y2 = self.endPoint!.y

    let (start, end) = getLines(0, ymin: 0, xmax: bounds.width, ymax: bounds.height, x1: x1, x2: x2, y1: y1, y2: y2)

    print(start, appendNewline: false)
    print(" - ", appendNewline: false)
    print(end)

    // Draw main line.
    self.drawLine(line: self.lineLayer!, start: start, end: end)
}

不幸的是,它还没有完全正常运行,因为在一半的情况下,返回正确的扩展行的返回if-construct没有返回任何有用的东西。我会尝试现在或明天解决这个问题。

但它应该让你开始

编辑:如果起点和终点都位于水平轴或垂直轴上,则似乎无效。它可以在不同的轴上工作。

在我添加了三个返回语句之后,代码现在完全正常运行:)

如果您查看记录的信息,您将看到绘制的线条实际上完全延伸到边界,而不是更远。