서클 교차로에서 배타적 영역 찾기


17

당신을 위해 기만적으로 도전하는 지오메트리 퍼즐이 있습니다!

An다른 원 이 있다면 그 B[n]안에 포함 된 총 면적 A이 원 안에 있지 않습니다B .

코드는 가능한 짧아야합니다.

입력

입력 내용에는 다음 정보가 포함되어야합니다.

  • 부동 소수점 숫자는 원의 반경을 나타내는 A.
  • 의 반지름을 나타내는 부동 소수점 숫자의 목록입니다 B.
  • 의 원 중심 목록입니다 B. 프로그램은 중심이 극좌표 또는 데카르트 좌표를 기대할 수 있습니다.
  • 선택적 n으로 B로 원 의 수 를 받을 수 있습니다 . 이 입력은 필요하지 않습니다.

원의 중심이 A원점, 즉 점 이라고 가정합니다 (0, 0).

두 원 B이 동일하다는 보장 은 없지만 모든 B교차 원 A, 중심이 B모두 바깥 A에 있거나 두 원이 B서로 교차 하지는 않습니다 . 솔루션이 다양한 에지 케이스를 처리 할 수 ​​있는지 확인하십시오.

어떤 순서로든 텍스트 입력 형식 (stdin 또는 해당 언어를 통해), 함수 매개 변수 또는 명령 줄 인수로 입력을받을 수 있습니다.

텍스트 입력을 받도록 선택한 경우 입력 사이에 하나 또는 두 개의 문자로 인쇄 가능한 ASCII 구분자가 있어야합니다.

산출

프로그램 또는 함수는 A의 원 안에 포함되지 않은 총 면적을 나타내는 단일 부동 소수점 숫자를 출력해야합니다 B. 귀하의 답변은 모든 테스트 사례에 대해 적어도 세 개의 유효 숫자로 정확해야합니다.

일반적인 규칙이 적용됩니다.

면적을 결정하기 위해 원 안의 샘플링 지점에 의존해서는 안됩니다.

원의 교차점을 자동으로 찾거나 원의 교차점에서 영역을 찾거나이 문제를 즉시 해결하는 내장 기능은 허용되지 않습니다.

테스트 사례

각 이미지에서 원 A은 파란색으로, 원 B은 녹색으로 채워지고 검은 색으로 채워집니다. 반환해야 할 영역이 빨간색으로 채워집니다.

( 내 솔루션을 확인한 Rainer P. 에게 감사드립니다 )

테스트 사례 1 :

A = {x: 0, y: 0, rad: 50}
B[0] = {x: 0, y: 0, rad: 100}

테스트 사례 1

Result: 0.00

테스트 사례 2 :

A = {x: 0, y: 0, rad: 100.000000}
B[0] = {x: 100.000000, y: 0.000000, rad: 50.000000}
B[1] = {x: 30.901699, y: -95.105652, rad: 50.000000}
B[2] = {x: -80.901699, y: -58.778525, rad: 50.000000}
B[3] = {x: -80.901699, y: 58.778525, rad: 50.000000}
B[4] = {x: 30.901699, y: 95.105652, rad: 50.000000}

테스트 사례 2

Result: 1.3878e+04

테스트 사례 3 :

A = {x: 0, y: 0, rad: 138}
B[0] = {x: 100, y: 0, rad: 100}
B[1] = {x: -50, y: -86, rad: 100} 
B[2] = {x: -93, y: 135, rad: 50}

테스트 사례 3

Result: 1.8969e+04

테스트 사례 4 :

A = {x: 0, y: 0, rad: 121.593585}
B[0] = {x: 81.000000, y: 107.000000, rad: 59.841457}
B[1] = {x: -152.000000, y: -147.000000, rad: 50.000000}
B[2] = {x: 43.000000, y: -127.000000, rad: 105.118980}
B[3] = {x: 0.000000, y: -72.000000, rad: 57.870545}
B[4] = {x: -97.000000, y: -81.000000, rad: 98.488578}
B[5] = {x: -72.000000, y: 116.000000, rad: 66.468037}
B[6] = {x: 2.000000, y: 51.000000, rad: 50.000000}

테스트 사례 4

Result: 1.1264e+04

테스트 사례 5 :

A = {x: 0, y: 0, rad: 121.605921}
B[0] = {x: 0.000000, y: -293.000000, rad: 250.000000}
B[1] = {x: 0.000000, y: -56.000000, rad: 78.230429}
B[2] = {x: 0.000000, y: -102.000000, rad: 100.000000}

테스트 사례 5

Result: 2.6742e+04

제안 된 독서 :

Fewell, MP "세 원의 공통 중첩 영역." 2006 년 10 월. 웹. http://dspace.dsto.defence.gov.au/dspace/bitstream/1947/4551/4/DSTO-TN-0722.PR.pdf .


나는 2 년 전에이 문제를 해결 하는 동안 두 서클에 대한 문제가 얼마나 간단한 지에 따라이 문제를 직접 해결하려고했습니다 . 나는 당신이 연결 한 논문을 읽게되었고 ... 몬테 카를로와 함께 가기로 결정했습니다. "솔루션이 영역을 결정하기 위해 원 안의 샘플링 지점에 의존해서는 안됩니다." D :
Martin Ender

한 서클에 B다른 서클이 포함 된 테스트 사례가없는 것 같습니다 . 그것을 추가 할 가치가있을 수 있습니다.
Martin Ender 2018 년

세 번째 테스트 사례를 확인할 수 있습니까? 을 받고 1.8970e+04있습니다.
LegionMammal978

@ MartinBüttner 나도 사고로 문제를 겪었습니다. 나는 내 솔루션에 너무 만족하지 않지만 작동하는 것 같습니다. 그 사건에 대해 약간의 시험을 작성하려고 노력할 것입니다, 감사합니다!
BrainSteel

@ LegionMammal978 예, 잘못 된 것 같습니다. 나는 원 사이의 교차점에 대해 다음 데이터가 : B[0] - A intersection: 20653.659515, B[1] - A intersection: 20757.824115, B[1] - B[0] intersection: 1841.847766, B[2] - A intersection: 1289.164541, 얻을 수있는 18969.69009대답한다.
BrainSteel

답변:


14

파이썬 2, 631 바이트

from cmath import*
C=input()
O,R=C[0]
def I(p,r,q,s):
 try:q-=p;d=abs(q*q);x=(r*r-s*s+d)/d/2;return[p+q*(x+z*(r*r/d-x*x)**.5)for z in-1j,1j]
 except:return[]
S=sorted
V=S(i.real for p,r in C for c in C for i in[p-r,p+r]+I(p,r,*c)if-R<=(i-O).real<=R)
A=pi*R*R
for l,r in zip(V,V[1:]):
 H=[]
 for p,t in C:
    try:
     for s in-1,1:a,b=[p.imag+s*(t*t-(p.real-x)**2)**.5for x in l,r];H+=[a+b,a,b,s,t,p],
    except:0
 a,b=H[:2];H=S(H[2:]);n=0;c=a
 for d in H:
    s=d[3];z=.5;H*=d<b
    for q,w,e,_,t,y in(c,min(d,b))*(n-s<(a<d)or[0]*n>H):\
g=phase((l+w*1j-y)/(r+e*1j-y));A-=abs(g-sin(g)).real*t*t/2-z*q*(r-l);z=-z
    n-=s
    if(a<d)*s*n==-1:c=d
print A

앞에있는 줄 바꿈 \은 쉽게 읽을 수 있으며 점수에 포함되지 않습니다.

STDIN을 통해 입력을 (center, radius)쌍 목록으로 읽습니다 . 여기서 형식 center은 복소수 X+Yj입니다. 목록의 첫 번째 원은 A (중심이 원점에있을 필요는 없음)이고 나머지 목록은 B 입니다. 결과를 STDOUT에 인쇄합니다.

Input:  (0+0j, 138),  (100+0j, 100), (-50+-86j, 100), (-93+135j, 50)
Output: 18969.6900901

설명

이것은 Martin Büttner의 Self-Intercrossting Polygon 과제 영역에 대한 솔루션 에서 (더 길고 훨씬 더 추악한 : P) 변형입니다 . 그것은 문제를 더 작은 조각으로 나누는 것과 같은 트릭을 사용하여 관리하기가 더 쉬워집니다.

우리는 모든 원 쌍 ( AB 의 원을 모두 고려) 사이의 교차점을 찾아 각각을 통해 수직선을 통과시킵니다. 또한 모든 수직선을 접하는 원에 전달합니다. A 와 교차하지 않는 모든 선을 버리고 나머지 모든 선은 A 의 왼쪽과 오른쪽 접선 사이에 있습니다.

그림 1

우리는 A 의 교차 영역 과 B 의 원의 결합 영역을 찾고 있습니다. 위의 그림에서 진한 빨간색 영역입니다. 이것이 결과를 얻기 위해 A 에서 빼야하는 영역입니다 .

연속 된 각 수직선 쌍 사이에서이 영역은 각 다리 옆에 "과도한"호 세그먼트가있는 일련의 수직 사다리꼴 (또는 삼각형, 또는 사다리꼴의 특수한 경우 선 세그먼트)로 나눌 수 있습니다. 우리가 우리만큼 많은 수직선을 통과한다는 사실은 경계 영역이 그보다 더 복잡하지 않다는 것을 보장합니다. 그렇지 않으면 두 선 사이에 추가 교차점이 있어야하고 따라서 수직선이 추가로 있어야하기 때문입니다. 질문.

그림 2

이 사다리꼴과 호 세그먼트를 찾으려면 연속 된 각 수직선 쌍에 대해이 두 선 사이에 올바르게 놓인 각 원의 호 세그먼트를 찾습니다 (물론 일부 원은 주어진 선 쌍 사이에 호 세그먼트가 없을 수 있음) .) 아래 그림에서 두 개의 빨간색 세로선을 고려할 때 6 개의 밝은 황색 선호 세그먼트가 있습니다. 원에 접하는 모든 수직선을 통과하므로 원에 두 선 사이에 호 세그먼트가 있으면 두 선이 반드시 교차하므로 나머지 알고리즘이 단순화됩니다.

이러한 모든 아크가 관련된 것은 아닙니다. 우리는 AB 의 합집합의 경계에있는 것들에만 관심이 있습니다 . 그것들을 찾기 위해 우리는 호를 위에서 아래로 정렬합니다 (호가 서로 교차하지 않을 수 있습니다. 임의의 아크는 다른 아크의 위 또는 아래에 있습니다.)

그림 3

우리 는 현재 내부 에있는 B 개의 원 수를 세면서 n 을 순서대로 호를 가로지 릅니다 . 만약 n은 우리가 내부에있는 동안 0에서 1로 변경 , 또는 우리의 상단 아크에있을 경우 동안 n은 0이 아닌 사다리꼴의 한쪽 다리에 다음 현재 아크 해당합니다. 만약 n 개의 우리 안에있는 동안 1에서 0으로 변경 우리의 바닥 호에 있다면, 또는 동안 N0이 아닌 경우 현재 호는 동일한 사다리꼴의 다른 구간에 해당합니다. 그러한 한 쌍의 호 (위의 그림에서 두 개의 밝은 노란색 호)를 찾으면 해당 사다리꼴 영역과 두 개의 호 세그먼트의 면적을 계산하고 A 에서 뺄 총 면적에 추가합니다 .

사다리꼴 영역뿐만 아니라 A 영역의 계산 은 매우 간단합니다. 각 호 세그먼트의 면적은 해당 원형 섹터의 면적에서 정점이 호 세그먼트의 두 끝점 인 삼각형의 면적에서 해당 원의 중심을 뺀 면적입니다.

그림 4


1
이것은 내가 고려했지만 B에서가 아닌 A에있는 3 자형과 사다리꼴을 찾아서 대상 영역을 직접 찾은 것을 제외하고는 일종의 해결책입니다.이 영역은 삼각형이나 사다리꼴에서 호 세그먼트를 빼서 찾아야합니다.
quintopia

@quintopia A 의 넓이를 계산할 필요가 없기 때문에 조금 더 짧을 수도 있습니다. 아마도 n 의 조건으로 조금만 연주하면 됩니다.
ELL

@quintopia OTOH, 당신은 다리 중 하나 옆에 양의 아크가있을 가능성을 설명해야합니다. 만약 그것이 A 의 호 세그먼트 라면 , 누가 알
겠습니까

탁월한 솔루션. 이것과 거의 같은 문제가 어제 밤 내 머릿속에 붙어 있었고, 누군가 그것을 해결하기를 정말로 원했습니다. 귀하의 솔루션은 내가 함께 일한 아이디어보다 낫습니다.
논리 기사
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.