我可以检测到两条线的交点,但是如果我的线条没有我的屏幕长度,它会检测到它不应该的位置。
预览: 因此,它不应该检测到这个交叉点,因为水平线不是那么长。
代码:
- (NSMutableArray *) intersectWithLines:(CGPoint)startPoint andEnd:(CGPoint)endPoint {
NSMutableArray *intersects = [[NSMutableArray alloc] init];
for(GameLine *line in [_lineBackground getLines]) {
double lineStartX = line.startPos.x;
double lineStartY = line.startPos.y;
double tempEndX = line.endPos.x;
double tempEndY = line.endPos.y;
double d = ((startPoint.x - endPoint.x)*(lineStartY - tempEndY)) - ((startPoint.y - endPoint.y) * (lineStartX - tempEndX));
if(d != 0) {
double sX = ((lineStartX - tempEndX) * (startPoint.x * endPoint.y - startPoint.y * endPoint.x) - (startPoint.x - endPoint.x) * (lineStartX * tempEndY - lineStartY * tempEndX)) / d;
double sY = ((lineStartY - tempEndY) * (startPoint.x * endPoint.y - startPoint.y * endPoint.x) - (startPoint.y - endPoint.y) * (lineStartX * tempEndY - lineStartY * tempEndX)) / d;
if([self isValidCGPoint:CGPointMake(sX, sY)]) {
[intersects addObject:[NSValue valueWithCGPoint:CGPointMake(sX, sY)]];
}
}
}
return intersects;
}
答案 0 :(得分:29)
如果我正确理解您的问题,您需要确定两个线段的交叉点。这应该使用以下方法:
- (NSValue *)intersectionOfLineFrom:(CGPoint)p1 to:(CGPoint)p2 withLineFrom:(CGPoint)p3 to:(CGPoint)p4
{
CGFloat d = (p2.x - p1.x)*(p4.y - p3.y) - (p2.y - p1.y)*(p4.x - p3.x);
if (d == 0)
return nil; // parallel lines
CGFloat u = ((p3.x - p1.x)*(p4.y - p3.y) - (p3.y - p1.y)*(p4.x - p3.x))/d;
CGFloat v = ((p3.x - p1.x)*(p2.y - p1.y) - (p3.y - p1.y)*(p2.x - p1.x))/d;
if (u < 0.0 || u > 1.0)
return nil; // intersection point not between p1 and p2
if (v < 0.0 || v > 1.0)
return nil; // intersection point not between p3 and p4
CGPoint intersection;
intersection.x = p1.x + u * (p2.x - p1.x);
intersection.y = p1.y + u * (p2.y - p1.y);
return [NSValue valueWithCGPoint:intersection];
}
答案 1 :(得分:6)
这是Hayden Holligan's answer的略微修改版本,可与Swift 3配合使用:
func getIntersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint {
let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x)
if distance == 0 {
print("error, parallel lines")
return CGPoint.zero
}
let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x)) / distance
let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x)) / distance
if (u < 0.0 || u > 1.0) {
print("error, intersection not inside line1")
return CGPoint.zero
}
if (v < 0.0 || v > 1.0) {
print("error, intersection not inside line2")
return CGPoint.zero
}
return CGPoint(x: line1.a.x + u * (line1.b.x - line1.a.x), y: line1.a.y + u * (line1.b.y - line1.a.y))
}
答案 2 :(得分:3)
Swift版
func getIntersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint {
let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x)
if distance == 0 {
print("error, parallel lines")
return CGPointZero
}
let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x)) / distance
let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x)) / distance
if (u < 0.0 || u > 1.0) {
print("error, intersection not inside line1")
return CGPointZero
}
if (v < 0.0 || v > 1.0) {
print("error, intersection not inside line2")
return CGPointZero
}
return CGPointMake(line1.a.x + u * (line1.b.x - line1.a.x), line1.a.y + u * (line1.b.y - line1.a.y))
}
答案 3 :(得分:2)
这是正确的等式:
+(CGPoint) intersection2:(CGPoint)u1 u2:(CGPoint)u2 v1:(CGPoint)v1 v2:(CGPoint)v2 {
CGPoint ret=u1;
double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
return ret;
}
此外,您可以检查此库以计算线交叉点: http://www.cprogramdevelop.com/5045485/
答案 4 :(得分:1)
这是Swift 4.2中的另一个解决方案。这在功能上与MartinR的解决方案相同,但是使用simd向量和矩阵对其进行清理。
/// Protocol adoped by any type that models a line segment.
protocol LineSegment
{
/// Point defining an end of a line segment.
var p1: simd_double2 { get }
/// Point defining an end of a line segment.
var p2: simd_double2 { get }
}
extension LineSegment
{
/// Calcualte the intersection between this line segment and another line
/// segment.
///
/// Algorithm from here:
/// http://www.cs.swan.ac.uk/~cssimon/line_intersection.html
///
/// - Parameter other: The other line segment.
/// - Returns: The intersection point, or `nil` if the two line segments are
/// parallel or the intersection point would be off the end of
/// one of the line segments.
func intersection(lineSegment other: LineSegment) -> simd_double2?
{
let p3 = other.p1 // Name the points so they are consistent with the explanation below
let p4 = other.p2
let matrix = simd_double2x2(p4 - p3, p1 - p2)
guard matrix.determinant != 0 else { return nil } // Determinent == 0 => parallel lines
let multipliers = matrix.inverse * (p1 - p3)
// If either of the multipliers is outside the range 0 ... 1, then the
// intersection would be off the end of one of the line segments.
guard (0.0 ... 1.0).contains(multipliers.x) && (0.0 ... 1.0).contains(multipliers.y)
else { return nil }
return p1 + multipliers.y * (p2 - p1)
}
}
该算法之所以有效,是因为如果您有由两个点 p 1 和 p 2定义的线段 a 和由 p 3 和 p 4 定义的线段 b a 和 b 上的点分别由
定义所以交点将在
p 1 + t a ( p 2 - p 1 )= p 3 + t b ( p 4 - p 3 )
可以重新排列为
p 1 - p 3 = t b ( p 4 - p 3 )+ t a ( p 1 - p 2 )
加上一点点扑克游戏,您可以得到以下等价物
p 1 - p 3 = A 。 t
其中 t 是向量(t b ,t a ), A 是其列的矩阵是 p 4 - p 3 和 p 1 >- p 2
方程式可以重新排列为
A -1 ( p 1 - p 3 )= t
左侧的所有信息都是已知的,或者可以通过计算得出 t 。可以将 t 的任意一个分量插入相应的原始方程式以获得交点(NB浮点数舍入误差将意味着两个答案可能并不完全相同,但非常接近)
请注意,如果线是平行的,则 A 的行列式将为零。另外,如果任一分量超出0 ... 1
范围,则需要扩展一个或两个线段才能到达交点。
答案 5 :(得分:0)
我知道答案已经给出,而且所有答案都是正确的,我觉得可以回答这个问题。就在这里。
$(document).ready(function () {
jQuery(function ($) {
var ft = FooTable.init('.table', {
"columns": $.get('/js/mycols.json'),
});
$('.table').on('ready.ft.table', function(e) {
$.ajax({
url: "/api/GetEvents",
dataType: "json",
type: "GET"
}).done(function (e) {
console.log(e);
ft.rows.load(e.value);
})
});
});
});
我是从this site那里得到的。
这也是非常简单和容易的。
快乐编码:)