Interseção de dois triângulos

19

Dados 4 pontos nos planos 2D A, B, C, D, calcule a área da região de interseção dos triângulos OABe OCD, onde Oé o centro do plano, tendo coordenadas (0, 0).

Algoritmos que são executados em complexidade de tempo constante (em termos de operações aritméticas) são incentivados, mas não forçados.

Regras

  • Cada ponto é representado como dois números reais, denota suas coordenadas X e Y.
    • Opcionalmente, se a sua linguagem de programação (ou alguma biblioteca da sua linguagem de programação) tiver um Pointtipo interno ou equivalente, é permitido que o Pointobjeto seja considerado como entrada.
  • A entrada é dada como 4 pontos, nos formatos, incluindo, entre outros:
    • Uma lista de 8 coordenadas.
    • Uma lista de 4 pontos, cada ponto pode ser representado em qualquer formato conveniente.
    • Duas listas de 2 pontos.
    • etc.
  • Você não pode assumir uma ordem específica dos pontos (ordem no sentido anti-horário ou ordem no sentido horário)
  • Você não pode assumir que o ponto Oé passado como entrada. Em outras palavras, o programa não deve receber e usar entradas estranhas.
  • Você não pode assumir que todos os pontos são diferentes. Em outras palavras, os triângulos podem estar degenerados. Você também precisa lidar com esse caso (veja os casos de teste abaixo)
  • A diferença absoluta ou relativa deve ser menor que nos casos de teste de amostra abaixo.10-3

Critérios de vitória

Isso é , a resposta mais curta em bytes ganha!

Casos de teste de amostra

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

Se alguém quiser, aqui estão as saídas para o primeiro grupo de casos de teste na forma exata:

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

Imagem ilustrativa para o caso de teste 5 1 1 3 3 4 4 -3(a área do quadrilátero verde é a saída esperada):

[ Imagem]

user202729
fonte
Um de seus casos de teste possui 9 entradas em vez de 8. 1,2 3,4 -0,3 4,2 5 3 7,6 -1,1 2,4 0
Kelly Lowder
1
@KellyLowder Fixed.
precisa saber é o seguinte

Respostas:

16

Wolfram Language (Mathematica) , 55 bytes

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

Experimente online!

Raspou alguns bytes da resposta trivial.

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

Substituir Areapor DiscretizeRegionmostrará a interseção.

insira a descrição da imagem aqui

A propósito, isso funcionará com qualquer simplex, não apenas triângulos.

-1 Byte graças a JungHwan Min

A sugestão de @ user202729 adicionou 4 bytes, mas produz 0 para triângulos degenerados

Kelly Lowder
fonte
1
O polígono também pode ser substituído pelo Simplex
Kelly Lowder
1
Mais um byte: {{0,0}}a {0{,}}(Isso funciona porque a avalia expressão de {Times[0, {Null, Null}]})
JungHwan Min
Falha neste caso de teste , listado em casos de teste de amostra.
user202729
Já observou que isso NÃO funciona no TIO. Não tenho certeza do que eles têm sob o capô.
precisa
1
Vejo que não funciona para a interseção de duas linhas. Meu mal por pular esse caso de teste. Tecnicamente, estes não são triângulos. Suponho que, se formos técnicos, talvez você deva mudar o título do post e a primeira frase. Também poderíamos ter uma discussão realmente esotérica sobre se a área é definida para um objeto unidimensional, mas prefiro que não.
quer
5

Python 2 + PIL, 341 318 313 284 270 bytes

Agradecimentos especiais a Dennis que prontamente adicionou PIL em TIO
-23 bytes, graças ao Sr. Xcoder

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

Experimente online! ou Experimente todos os casos de teste

Para calcular a diferença, desenhe literalmente os triângulos e verifique a quantidade de pixels pintados nas duas imagens.
Este método inseriu um erro de arredondamento, que é suavizado aumentando o tamanho da imagem.

Explicação

#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
Cajado
fonte