两个三角形的交点


19

给定的2D平面4点A, B, C, D,计算三角形的交叉区域的面积OABOCD,其中O是该平面的中心,具有坐标(0, 0)

鼓励以恒定时间复杂度(就算术运算而言)运行的算法,但不强制执行。

规则

  • 每个点都用两个实数表示,分别表示它们的X和Y坐标。
    • (可选)如果您的编程语言(或某种编程语言库)具有内置Point类型或等效类型,则允许将Point对象作为输入。
  • 输入以4点的形式给出,格式包括但不限于:
    • 8个坐标的列表。
    • 4点的列表,每个点都可以任何方便的格式表示。
    • 2点的两个清单。
    • 等等
  • 您不能假设这些点的特定顺序(逆时针顺序或顺时针顺序)
  • 您不能假定该点O已作为输入传递。换句话说,程序不得使用和使用无关的输入。
  • 您不能假设所有要点都不同。换句话说,三角形可以退化。您还需要处理该案例(请参见下面的测试案例)
  • 绝对或相对差必须小于下面的样本测试用例。10-3

获奖标准

这是,以字节为单位的最短答案!

样本测试用例

Ax Ay Bx By Cx Cy Dx Dy area

5 1 1 3 -1 0 0 -1 0
5 1 1 3 -1 0 0 0 0
5 1 1 3 0 0 0 0 0
5 1 1 3 3 4 4 -3 4.50418
5 1 1 3 1 2 2 1 1.5
5 1 1 3 -2 5 4 -2 1.74829
5 1 1 3 -2 5 5 4 2.96154
5 1 1 3 3 5 5 4 1.88462
5 1 1 3 3 5 3 1 3.92308
5 1 1 3 3 5 4 -1 5.26619
5 1 1 3 5 1 4 -1 0
5 1 1 3 5 1 1 3 7
1 3 1 3 5 1 1 3 0
1 3 1 3 1 3 1 3 0
4 8 4 -1 -2 6 -2 -3 0

1.2 3.4 -0.3 4.2 5 7.6 -1.1 2.4 2.6210759326188535
3.1 0.6 0.1 7.2 5.2 0.7 0.9 8 9.018496993987977

如果有人愿意,以下是第一个测试用例组的输出形式:

0
0
0
46375/10296
3/2
1792/1025
77/26
49/26
51/13
23345/4433
0
7
0
0
0

测试用例的插图图像5 1 1 3 3 4 4 -3(绿色四边形的面积是预期的输出):

[ 图片]


您的一个测试用例有9个输入,而不是8个。1.2 3.4 -0.3 4.2 5 3 7.6 -1.1 2.4 0
Kelly Lowder

1
@KellyLowder固定。
user202729

Answers:


16

Wolfram语言(Mathematica),55个字节

0&@@Area@BooleanRegion[And,Simplex[{0{,}}~Join~#]&/@#]&

在线尝试!

将平凡的答案减少了几个字节。

%@{{{5, 1}, {1, 3}}, {{3, 4}, {4, -3}}} yields 46375/10296 or 4.504176379

替换AreaDiscretizeRegion将显示相交。

在此处输入图片说明

顺便说一下,这将适用于任何单纯形,而不仅仅是三角形。

-1字节感谢郑焕敏

@ user202729的建议增加了4个字节,但对于退化的三角形它却产生0


1
多边形也可以代替Simplex
Kelly Lowder

1
另一个字节:{{0,0}}to {0{,}}(这有效,因为表达式的计算结果为{Times[0, {Null, Null}]}
JungHwan Min

此测试用例失败,在示例测试用例中列出了该测试用例。
user202729 '17

已经注意到,这不适用于TIO。不知道他们的内幕。
凯莉·洛德

1
我看到这不适用于两条线的交点。我不好跳过那个测试用例。从技术上讲,这些不是三角形。我想,如果我们要获取技术知识,也许您应该更改帖子的标题以及第一句话。关于是否甚至为一维对象定义区域,我们也可能进行了深奥的讨论,但我宁愿不这样做。
凯莉·劳德

5

蟒2 + PIL,341个 318 313 284 270字节

特别感谢Dennis,感谢Xcoder先生立即在TIO -23字节上添加了PIL

import PIL.Image as I,PIL.ImageDraw as D
l=[i*1000for i in[0,0]+input()+[0,0]]
z=zip(*[[i-min(t)for i in t]for t in l[::2],l[1::2]])
print sum(map(int.__mul__,*map(lambda i,c:D.Draw(i).polygon(c,1)or i.getdata(),map(I.new,'11',[[max(l)-min(l)]*2]*2),[z[:3],z[3:]])))/1e6

在线尝试!尝试所有测试用例

为了计算差异,这实际上是绘制三角形并检查两个图像中绘制的像素数量。
该方法插入了舍入误差,通过增加图像尺寸可以消除该误差。

说明

#the image/triangles are enlarged to increase the precision
#a pair of zeros are inserted in the start and at the end, this way "l" will have all 6 points to draw the triangles 
l=[i*1000for i in[0,0]+input()+[0,0]]
#split the input in x and y, where x=l[::2] and y=l[1::2]
#get the smallest number on each list, that will be "0" if there is no negative number, to be used as offset.
#this will be used to overcome the fact that PIL won't draw on negative coords
#zip "x" and "y" lists, to create a list containing the points
z=zip(*[[i-min(t)for i in t]for t in x,y])
#create 2 (B&W) blank images
#where the size is the difference between the smallest and the largest coord.
map(I.new,'11',[[max(l)-min(l)]*2]*2)
#draw both triangles and return the pixel list of each image
map(lambda i,c:D.Draw(i).polygon(c,1)or i.getdata(),<result of previous line>,[z[:3],z[3:]])
#count the amount of overlapping pixels by summing the color of each pixel, if the pixel is "1" in both images, then the triangles are overlapping, then the amount of pixels is divided by the initial enlarging factor squared (1e6)
print sum(map(int.__mul__,*<result of previous line>))/1e6
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.