2017-08-06 2 views
1

私は、画面に線を引くためにCAShapeLayerを使用します。メソッドでtouchesEnded私は "ラインがポイントを通過するかどうかチェックしますか?"私のコードでは、画面の任意の部分を押すとのメソッドが常にtrueを返します。おそらく、私は問題があるline.frame =(view?.bounds)!。どうすれば修正できますか? 私の悪い英語を申し訳ありません。CAShapeLayer。ラインはポイントを通過しますか?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 

    let touch = touches.first 
    let firstPosition = touch?.location(in: self) 

    if atPoint(firstPosition!) == lvl1 { 

     let firstPositionX = firstPosition?.x 
     let firstPositionY = frame.size.height - (firstPosition?.y)! 
     view?.layer.addSublayer(line) 
     line.lineWidth = 8 
     let color = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1).cgColor 
     line.strokeColor = color 
     line.fillColor = nil 
     line.frame = (view?.bounds)! 
     path.move(to: CGPoint(x: firstPositionX!, y: firstPositionY)) 

    } 

} 

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 

    let touch = touches.first 
    let firstPosition = touch?.location(in: self) 

    if atPoint(firstPosition!) == lvl1 { 

     let firstPositionX = firstPosition?.x 
     let firstPositionY = frame.size.height - (firstPosition?.y)! 
     path.addLine(to: CGPoint(x: firstPositionX!, y: firstPositionY)) 
     line.path = path.cgPath 

    } 
} 


override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 

    if line.contains(screenCenterPoint) { 
     print("ok") 
    } 

} 
+0

[線分と点](http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line)との距離を計算し、値がある値以下になるかどうかを確認することをお勧めします。 – Rob

答えて

3

通報

方法CAShapeLayer戻りtruefunc contains(_ p: CGPoint) -> Bool層の境界点が含まれている場合。 (see documentation

にポイントが含まれているかどうかを確認するためには使用できません。

ただし、指定された点がパスにの内部であるかどうかを返すクラスCGPathに同じ名前の別のメソッドがあります。しかし、ストロークあなたのパスとを記入していないので、この方法でも希望の結果が得られません。

let outline = path.cgPath.copy(strokingWithWidth: line.lineWidth, lineCap: .butt, lineJoin: .round, miterLimit: 0) 

をそして、輪郭線の内部はあなたのscreenCenterPoint

if outline.contains(screenCenterPoint) { 
    print("ok") 
} 

Stroke vs outlineが含まれているかどうかを確認:トリックは使用して、パスの概要を作成することです

ソリューション

パフォーマンスの考慮

タッチはを終了した場合にのみ、あなたが封じ込めをチェックしているので、私はパスのアウトラインを作成することは、あまりにも多くのオーバーヘッドを追加しないと思います。

あなたは、このメソッドは、毎秒多くの時間と呼ばれているので、いくつかのオーバーヘッドが生じることのアウトラインを計算し、touchesMoved関数の内部例えば、リアルタイムで封じ込めをチェックしたい

。また、パスが長くなればなるほど、アウトラインの計算に時間がかかります。

リアルタイムでは、最後に描画されたセグメントのアウトラインのみを生成し、そのアウトラインにポイントが含まれているかどうかを確認する方がよいでしょう。

オーバーヘッドを大幅に削減したい場合は、独自の包含機能を作成できます。直線における点の封じ込めはかなり単純であり、以下の式に還元することができる。widthendstartからラインを考える

p

計算:

  • dx = start.x - end.x
  • dy = start.y - end.y
  • a = dy * p.x - dx * p.y + end.x * start.y - end.y * start.x
  • b = hypot(dy, dx)

場合ラインがポイントpが含まれています:pはラインのバウンディングボックスである

abs(a/b) < width/2

+0

驚くべき答え! –

+0

ありがとうございました。それは私の問題を解決しました。 –

関連する問題