점이 삼각형 안에 있는지 확인하십시오


40

당신의 목표는 주어진 2D 점 X가 주어진 꼭짓점 A, B, C를 가진 삼각형의 영역 내에 있는지를 결정하는 것입니다.

테스트 지점 X와 3 개의 삼각형 정점 (총 8 개의 좌표)의 좌표를 취하고 해당 삼각형 안에 점이 있으면 True를, 외부에 있으면 False를 반환하는 함수를 작성하십시오.

에지 케이스에 대해 걱정하지 마십시오. 점이 삼각형의 경계 (가장자리 또는 꼭지점)에 있거나 삼각형이 실제로 선분이면 코드가 충돌을 포함하여 모든 작업을 수행 할 수 있습니다. 또한 수치 안정성 또는 부동 소수점 정밀도에 대해 걱정하지 마십시오.

코드는 명명 된 함수 여야합니다. 코드 스 니펫은 허용되지 않습니다.

가장 적은 캐릭터가 승리합니다.

입력:

좌표를 나타내는 8 개의 실수. 숫자는 범위 안에 있습니다 (-1,1).

정확한 입력 형식은 유연합니다. 예를 들어 8 개의 숫자, 8 개의 숫자 목록, 각각 튜플에 의해 주어진 4 개의 점 목록, 2 * 4 행렬, 4 개의 복소수, 2 개의 x 좌표 및 y 좌표 목록, 등등.

입력은 추가 데이터없이 일부 컨테이너의 숫자 일뿐입니다. 사전 처리를 수행하기 위해 입력을 사용할 수 없으며, 점을 오름차순으로 y 좌표로 지정해야하는 등 입력에 대한 제한이 필요하지 않습니다. 입력은 8 개의 좌표를 허용해야합니다 (앞서 언급 한 엣지 케이스에서는 코드가 임의로 작동 할 수 있음).

입력 형식을 명시하십시오.

산출:

해당 부울 True/ False, 해당 숫자 1/ 0또는 언어의 아날로그 중 하나입니다.

테스트 사례

입력에는 [X,A,B,C]4 개의 튜플, 테스트 지점이 먼저, 3 개의 삼각형 정점 이 나열 됩니다. 나는 출력이 있어야 True하고 출력되어야하는 그룹으로 그룹화했습니다 False.

True 인스턴스 :

[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]

False 인스턴스 :

[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]

캐릭터의 정의는 무엇입니까? 아스키? 7 비트로 인코딩 할 수 있습니까? 바이트? 유니 코드?
isaacg

당신은 무엇을 제안합니까? 압축 코드를 사용하는 솔루션이 이미 있습니다.
xnor

일반적으로 바이트가 비 ASCII 문자에 사용된다고 생각합니다. 그렇지 않으면 Utf-32의 이점은 극복 할 수 없기 때문입니다.
isaacg

글쎄, 나는 지금 돌아갈 수 없다. 모든 유니 코드 문자는 문자입니다. 원하는 경우 압축하십시오.
xnor

답변:


19

자바 / ECMAScript를 6 161 159 152분의 158

자바 스크립트 :

function $(t,r,i,a,n,g,l,e){b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

ECMAScript 6 버전 (m.buettner 덕분에 6 자 저장)

$=(t,r,i,a,n,g,l,e)=>{b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

다음과 같이 호출하십시오 (return true또는 false).

$(pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y);

이 답변의 코드를 기반으로 멋진 무게 중심 좌표 수학을 사용합니다 . 당신의 독서 즐거움을위한 ungolfed 버전은 다음과 같습니다 :

function $ (pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y) {
  var A =  (-v2Y * v3X + v1Y * (-v2X + v3X) + v1X * (v2Y - v3Y) + v2X * v3Y) / 2;
  var sign = A < 0 ? -1 : 1;
  var s = (v1Y * v3X - v1X * v3Y + (v3Y - v1Y) * pointX + (v1X - v3X) * pointY) * sign;
  var t = (v1X * v2Y - v1Y * v2X + (v1Y - v2Y) * pointX + (v2X - v1X) * pointY) * sign;
  return s > 0 && t > 0 && s + t < 2 * A * sign;
}

12
매개 변수 이름에 대해서만 +1!
Matt

문자 계산 사용자 스크립트를 왜 깨야합니까 ???
kitcar2000

@ kitcar2000 무슨 뜻인가요?
Abraham

규칙은 바이트가 아닌 문자가 계산된다고 말합니다. 그래서 당신은 이것을 사용할 수 있습니다 : xem.github.io/obfuscatweet 122 자에 맞게
xem

1
내가 착각 했습니까? 아니면 (a*(l-n)+i*(g-e)+n*e-g*l)대신 사용할 수 (-g*l+a*(-n+l)+i*(g-e)+n*e)있습니까?
Zacharý

19

파이썬 2.7 128 127 117 110 109 103 99 95 94 91 90

나의 첫 번째 코드 골프 시도!

암호

f=lambda x,y,t:sum(a*y+c*b+d*x<d*a+c*y+b*x for i in(0,1,2)for a,b,c,d in[t[i-1]+t[i]])%3<1

입력 (x, y, t)로 취합니다. 여기서 (x, y)는 우리가 확인하는 점이고 t는 삼각형 t = ((x1, y1), (x2, y2), (x3, y3))입니다.

설명

행렬의 행렬식을 계산하고 있습니다.

| 1 x1 y1 |      | 1 x2 y2 |      | 1 x3 y3 |
| 1 x2 y2 | ,    | 1 x3 y3 | ,    | 1 x1 y1 | .
| 1 x  y  |      | 1 x  y  |      | 1 x  y  |

이 결정 요인은 삼각형의 측면에서 점 (x, y)까지의 부호있는 거리를 나타냅니다. 모두 같은 부호를 가지면 점은 모든 선의 같은쪽에 있으므로 삼각형에 포함됩니다.

위의 코드 a*y+c*b+d*x-d*a-c*y-b*x에서 이러한 행렬 중 하나를 결정합니다.

나는 사실을 사용하고 True+True+True==3있으며 False+False+False==0이러한 결정 요인이 모두 동일한 부호를 갖는지 확인합니다.

t[-1]대신을 사용하여 Python의 음수 목록 인덱스를 사용 합니다 t[(i+1)%3].

s가 0 또는 3인지 확인 하는 s%3<1대신 사용하는 아이디어에 대해 Peter에게 감사드립니다 s in(0,3)!

세이지 매스 버전

실제로 다른 솔루션은 아니므 로이 답변에 80 자를 사용하는 sagemath 솔루션을 포함시킵니다 .

f=lambda p,t,o=[1]:sum([det(Matrix([o+t[i-1],o+t[i],o+p]))<0for i in 0,1,2])%3<1

경우 p=[x,y], 그리고t=[[x1,y1],[x2,y2],[x3,y3]]


1
s in (0,3)단축 될 수 s%3<1있습니까?
피터 테일러

1
부정적인 지표의 사용은 더 많은 일을 저장 불통 할 수 있습니다 -1,0,1 ... t[i]+t[i+1]에 해당0,1,2 ... t[i-1]+t[i]
피터 테일러

@PeterTaylor 그렇습니다! in -1,0,1이 글을 읽기 전에 공간을 제거 했습니다. 실제로 당신의 길은 더 읽기 쉽기 때문에 어쨌든 사용할 것입니다.
Alex L

1
코드 골프에 오신 것을 환영합니다! 괄호를 묶는 sum경우 내부의 목록 이해를위한 대괄호를 제거 할 수 있습니다 0,1,2.이 경우 공백을 대체하여 문자를 사용하십시오. 파이썬은 대괄호없는 이해가 함수에 전달되도록 허용하지만 벌거 벗은 튜플의 쉼표는 함수 1,2,3를 별도의 인수로 구문 분석하려고하기 때문에 혼동됩니다.
xnor

16

수학, 67 바이트

f=Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])&

함수는 두 인자 포인트 얻어 X포인트들의리스트 {A,B,C}로 지칭되는, #그리고 #2각각이. 당신이 전화하면

f[X,{A,B,C}]

그런 다음 #as X#2을 얻습니다 {A,B,C}. (이 코드 안에 중첩이 다른 익명 함수임을 참고 - ##2. 그 안에 다른 의미를 가지고)

다음은 함수 자체에 대한 설명입니다.

                                              x=#;#2            & (* Save X into a variable x, but evaluate to {A,B,C}. *)
                                    Partition[x=#;#2,2,1,{1,1}] & (* Get a cyclic list of pairs {{A,B},{B,C},{C,B}}. *)
       (                        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Define an anonymous function and apply it to each 
                                                                     of the above pairs. The two elements are referred 
                                                                     to as # and #2. *)
       (          (#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Subtract the two points. For a pair of vertices 
                                                                     this yields a vector corresponding to the edge 
                                                                     between them. *)
        {#2,-#}&                                                  (* An anonymous function that takes two values, 
                                                                     reverses them, inverts the sign of one of them 
                                                                     and puts them into a list. *)
       ({#2,-#}&@@(#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Applied to the edge, this yields its normal. *)
       ({#2,-#}&@@(#-#2).(x-#)  &@@@Partition[x=#;#2,2,1,{1,1}])& (* Take the scalar product of that normal with a
                                                                     vector from a vertex to x. This is projection of 
                                                                     this vector onto that normal and hence the SIGNED
                                                                     distance of x from the edge. *)
       ({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check the sign of that distance, the exact mapping 
                                                                     between (left, right) and (True, False) is 
                                                                     irrelevant, as long as it's consistent. *)
Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check if all signs are equal - that is, if point X 
                                                                     lies on the same side of all edges. This is 
                                                                     equivalent to check that the point is inside the 
                                                                     triangle. *)

참고이 기능을 것입니다 실제로 작동 어떤 볼록 N-곤만큼의 정점 중 하나를 시계 방향 또는 반 시계 방향으로 순서대로 부여한다.


거리의 곱이 양의 부호가 모두 같은지 확인하는 것이 더 효율적이지 않습니까? 나는 Mathematica는 아니지만 더 쉬워 보일 것 같습니다.
isaacg

@isaacg 세 가지 용어가 있으므로 모두 부정적이면 제품이 음성이고 모두 긍정적이면 제품은 양성입니다. 두 숫자의 부호가 동일해야 접근 방식이 작동합니다.
마틴 엔더

왜 사용하지 Det않습니까?
alephalpha

@alephalpha 글쎄요, 아마 생각하지 않았기 때문일 것입니다. : P ... 나는 그것에 대해 살펴볼 것이다
Martin Ender

@alephalpha 흠 아니, 지금은 적은 문자로 세 가지 필수 행렬을 만드는 방법을 찾을 수 없습니다.
마틴 엔더

7

CJam, 66 63 59 52 46 34 32 31 30 28 자

"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

유니 코드 문자열을 변환 한 후 다음 코드 ( 33 바이트 )가 평가됩니다.

{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T

X [A B C]각 점이 형식 인 입력으로 예상 됩니다 [double double]. 출력은 1 또는 0입니다.

온라인으로 사용해보십시오.

6 자 (압축되지 않은 13 바이트의 코드)를 저장해 준 user23013 에게 큰 감사를드립니다 !

테스트 사례

$ cat triangle.cjam
"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

[
  [-0.31961 -0.12646] [ [0.38478 0.37419]   [-0.30613 -0.59754] [-0.85548 0.6633]   ] T
  [-0.87427 -0.00831] [ [0.78829 0.60409]   [-0.90904 -0.13856] [-0.80685 0.48468]  ] T
  [0.28997 -0.03668]  [ [-0.28362 0.42831]  [0.39332 -0.07474]  [-0.48694 -0.10497] ] T
  [-0.07783 0.04415]  [ [-0.34355 -0.07161] [0.59105 -0.93145]  [0.29402 0.90334]   ] T
  [0.36107 0.05389]   [ [0.27103 0.47754]   [-0.00341 -0.79472] [0.82549 -0.29028]  ] T
  [-0.01655 -0.20437] [ [-0.36194 -0.90281] [-0.26515 -0.4172]  [0.36181 0.51683]   ] T
  [-0.12198 -0.45897] [ [-0.35128 -0.85405] [0.84566 0.99364]   [0.13767 0.78618]   ] T
  [-0.03847 -0.81531] [ [-0.18704 -0.33282] [-0.95717 -0.6337]  [0.10976 -0.88374]  ] T
  [0.07904 -0.06245]  [ [0.95181 -0.84223]  [-0.75583 -0.34406] [0.16785 0.87519]   ] T
  [-0.33485 0.53875]  [ [-0.25173 0.51317]  [-0.62441 -0.90698] [-0.47925 0.74832]  ] T
  [-0.99103 0.43842]  [ [0.78128 -0.10985]  [-0.84714 -0.20558] [-0.08925 -0.78608] ] T
  [0.15087 -0.56212]  [ [-0.87374 -0.3787]  [0.86403 0.60374]   [0.01392 0.84362]   ] T
  [0.1114 0.66496]    [ [-0.92633 0.27408]  [0.92439 0.43692]   [0.8298 -0.29647]   ] T
  [0.87786 -0.8594]   [ [-0.42283 -0.97999] [0.58659 -0.327]    [-0.22656 0.80896]  ] T
  [0.43525 -0.8923]   [ [0.86119 0.78278]   [-0.01348 0.98093]  [-0.56244 -0.75129] ] T
  [-0.73365 0.28332]  [ [0.63263 0.17177]   [-0.38398 -0.43497] [-0.31123 0.73168]  ] T
  [-0.57694 -0.87713] [ [-0.93622 0.89397]  [0.93117 0.40775]   [0.2323 -0.30718]   ] T
  [0.91059 0.75966]   [ [0.60118 0.73186]   [0.32178 0.88296]   [-0.90087 -0.26367] ] T
  [0.3463 -0.89397]   [ [0.99108 0.13557]   [0.50122 -0.8724]   [0.43385 0.00167]   ] T
  [0.88121 0.36469]   [ [-0.29829 0.21429]  [0.31395 0.2734]    [0.43267 -0.78192]  ] T
]p;

$ cjam triangle.cjam
[1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0]

명명 된 함수입니까?
Martin Ender

@ m.buettner : 종류. 공식 위키는 다음 말한다 - 프로그램 섹션으로 구분 블록 {}단일 단위로 취급합니다. C / java의 코드 블록과 유사하지만 블록은 일류 객체이며 변수에 할당 될 수 있습니다 (따라서 함수 정의).
Dennis

1
@xnor는 1m<@m*3 쌍의 X와 i+1삼각형 의 다음 ( 번째) 정점을 준비합니다. @-@@-현재 ( ith) 정점을 원점으로 이동시킵니다 (그리고 그렇지 않은 경우 미러링 @-\@-되지만 중요하지 않음). @@*@@*>교차 곱 (일명 결정 요인)의 z 축을 계산하고 1음수 인 경우 반환 합니다. :+3%!모두 같거나, 즉 3이 모두 음수인지, 음수가 아닌지 여부를 반환합니다. 이는 에지 사례를 제외하고 양수를 의미합니다. 나는 골프보다 CJam을 읽는 것이 더 어렵다고 생각합니다.
jimmy23013

1
37 바이트 : {[_1m<\]z\f{f{+~@-@@-}~@@*@@*>})-!}:T. 유니 코드 안전을 위해 2m>또는 사용하십시오 Wm<.
jimmy23013

1
33 바이트 :{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T
jimmy23013

5

C – 156 바이트

입력은 X에 3 개의 float, Y에 3 개의 float, 및 테스트 포인트에 대해 x와 y를 분리 한 배열입니다. 보너스 : 모든 엣지 케이스를 처리합니다!

int f(float*X,float*Y,float x,float y){int i,j,c=0;for(i=0,j=2;i<3;j=i++)if(((Y[i]>y)!=(Y[j]>y))&&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[i]))c=!c;return c;}

PNPOLY에서 채택되었습니다.


i;j;c;f(float*X,float*Y,float x,float y){for(c=i=0,j=2;i<3;)c^=(Y[i]>y)-(Y[j]>y)&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[j=i++]);return c;}
137-

@bebe-구문 오류가 발생합니다.
Derek 朕 會 功夫

하지 않는 구문 오류가 발생합니다.
bebe

4

Pyth 1.0.5 , 57 54 51

DgYb=Z0J'bWbK;bDiHNR*-'H'K-@N1@K1~Z>iYJiJY=JK)R!%Z3

테스트 지점과 삼각형의 정점 목록이라는 두 가지 입력을받는 함수 g를 정의합니다. 출력 TrueFalse. 참고 : 입력, 특히 b의 정점 목록을 삭제합니다.

여기서 사용해보십시오 . 마지막 몇 문자 gvwvw는 다음 두 줄에서 테스트 케이스가있는 함수를 호출하십시오.

알고리즘을 기반으로

설명:

DgYb                  Define g(Y,b):
=Z0                     Z=0
J'b                     J=b[0]              (No = is needed because j is special).
Wb                      While len(b)>0:     (While b:)
K;b                       K=b.pop()
DiHN                      Define i(H,N):    
R*-'H'K-@N1@K1              Return half of the linked equation.
~ZiYJiJY                  Z+=i(Y,J)>i(J,Y)
=JK                       J=K
)                       Wend
R!%Z3                   return not Z%3==0   (True iff Z == 0 or 3)

CJam-Pyth 전쟁이 계속됩니다!


명명 된 함수 여야합니다. 되어 wSTDIN 입력을 복용?
xnor

@ xnor 죄송합니다. 해당 설명을 놓쳤습니다. 편집합니다.
isaacg

@xnor 답을 출력하는 함수가 허용됩니까, 아니면 답을 반환해야합니까? 현재 이것은 답변을 인쇄하지만 한 번 더 문자를 반환하도록 할 수 있습니다.
isaacg 2013

답을 반환하십시오.
xnor

카운터 Z를 빈 집합 으로 교체하여 문자를 저장 Z|=한 다음 길이를 테스트하여 0또는 만 보이는지 확인할 1수 있습니까? 이 전략은 Python에서 더 길어졌지만 Pyth 프리미티브를 사용하는 것이 좋습니다.
xnor

4

J 64 45 (할당되지 않은 42)

c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)

사물이 기능을 수행하는 데 필요하지 않으므로 계산 여부를 잘 모릅니다. 유연한 입력 활용 : (1 + 정점 수) x (공간의 크기) 배열을 원합니다.

여기에 몇 가지 추가 점수를 주길 바라고 ... : 이것은 평면의 삼각형뿐만 아니라 3D 공간의 3면 피라미드 등의 모든 차원에 적용됩니다. 또한 단면의 꼭짓점 수가 (n + 1)보다 작은 경우에도 작동하며 단면에 대한 점의 투영이 내부에 있는지 여부를 계산합니다.

barycentric coordinates 로 변환 한 다음 음수를 확인하여 점이 외부에 있음을 나타냅니다. J가 음수로 _를 사용한다는 것을 명심하십시오

NB. example in triangle
D =: 4 2 $ 1 1 0 0 3 0 0 2 NB. 4 rows , x first, then the vertices of the triangle

NB. subtract last vertex coordinates from the rest and drop reference node
n=: (}:-"1{:)

NB. preprocessed to barycentric coordinates
bar=: {. (, 1 - +/)@%. |:@}.

NB. all positive
ap =: *./@(>:&0)

insided =: ap@bar@n

inside D
1

주어진 예에서 실행 :

   true =: 0 : 0
[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
)

   false =: 0 : 0
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]
)
   NB. replace - by _ to avoid problems
   NB. cut up per row, drop the [ ] and convert to numbers
   $dat_t =: ((4 2 $ ".)@}:@}.;._2) (true='-')} true ,: '_'
10 4 2
   $dat_f =: ((4 2 $ ".)@}:@}.;._2) (false='-')}false,: '_'
10 4 2
   NB. this results in arrays with shape 10 4 2

   NB. for each 4 x 2 array (rank 2), do c for all true instances
   c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)
   c"2 dat_t
1 1 1 1 1 1 1 1 1 1
   NB. the same for the false ones, demonstrating anonymous usage
   NB. still a function though (or verb in J parlance)
   *./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)"2 dat_f
0 0 0 0 0 0 0 0 0 0

명명 된 함수를 요청했기 때문에 할당 문자가 계산됩니다. 다음은 다각형을 일반화하기위한 몇 가지 사항입니다! ······
xnor

사실, 나는 다각형을 일반화하지 않지만 최대 N+1정점을 가진 N- 차원 심플 렉스로 일반화합니다 . 예를 들어 3 차원 공간에서 4 개의 정점 피라미드, 4 차원 공간에서 5 개의 정점 심플 렉스. 정점의 수는보다 작을 수 있습니다 N+1.이 경우 알고리즘은 단면이 존재하는 초평면에 대한 직교 투영이 단면 내부에 있는지 여부를 확인합니다 (예 : 2 차원의 2 포인트 단면이 선에 투영되고 확인 됨) 이 투영이 종점 사이에 있는지의 여부)
jpjacobs

4

HTML5 + JS, 13b + 146b / 141b / 114 자

HTML :

<canvas id=C>

JS (146b) :

// @params: t1x, t1y, t2x, t2y, t3x, t3y, pointx, pointy
function T(a,b,c,d,e,f,g,h){with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

또는 ES6 (141b) :

T=(a,b,c,d,e,f,g,h)=>{with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

또는 ES6 유니 코드 난독 처리 (114 자) :

eval(unescape(escape('𥀽𚁡𛁢𛁣𛁤𛁥𛁦𛁧𛁨𚐽🡻𭱩𭁨𚁃𛡧𩑴𠱯𫡴𩑸𭀨𘠲𩀢𚐩𬡥𭁵𬡮𘁢𩑧𪑮𤁡𭁨𚀩𛁭𫱶𩑔𫰨𨐬𨠩𛁬𪑮𩑔𫰨𨰬𩀩𛁬𪑮𩑔𫰨𩐬𩠩𛁦𪑬𫀨𚐬𘐡𩱥𭁉𫑡𩱥𡁡𭁡𚁧𛁨𛀱𛀱𚐮𩁡𭁡𦰳𧑽').replace(/uD./g,'')))

데모 : http://jsfiddle.net/xH8mV/

다음으로 만든 유니 코드 난독 화 : http://xem.github.io/obfuscatweet/


점이 측면에 가까울 때 올바른 결과를 얻지 못하는 것 같습니다 : jsfiddle.net/L2B2A 모든 입력이 (-1,1) 사이에 있고 코드가 4 픽셀 만 테스트하기 때문이라고 생각합니다 기원.
Derek 朕 會 功夫

맞습니다. 예제에 맞게 [-1,1] 내부의 삼각형을 처리하도록 캔버스의 원점과 배율을 변경해야합니다. 그런데 왜 그 삼각형이 그렇게 작습니까?
xem

문제는 모든 xy가 -1과 1 사이에 있다고 말합니다. 왜 그런지 모르겠지만 모든 입력에 1e7을 곱하여 (정밀도를 유지하기 위해) 올바른 결과를 얻을 수 있다고 생각합니다. D
Derek 朕 會 功夫

매우 영리한 그래픽 솔루션!
xnor

3

파이썬 (65)

사람들이 제출을 마치고있는 것 같습니다. 그래서 내 질문에 내 자신의 해결책을 게시 할 것입니다.

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

X는 테스트 포인트를 나타내는 복소수이며 L, 각각 복소수 인 3 개의 포인트리스트입니다.

먼저, 덜 골프화 된 코드를 설명하겠습니다.

def f(X,A,B,C):A-=X;B-=X;C-=X;return((A/B).imag>0)==((B/C).imag>0)==((C/A).imag>0)

우리는 포인트를 이동 A,B,C,X즉 있도록 X이다 파이썬의 내장 복잡한 연산을 활용, 원점에. 원점이의 볼록 껍질에 포함되어 있는지 확인해야합니다 A,B,C. 이것은 선 세그먼트 AB, BC 및 AC의 항상 같은 쪽 (왼쪽 또는 오른쪽)에있는 원점과 같습니다.

세그먼트는 ABA에서 B로 얻을 적은 180도보다 왼쪽 경우 하나의 여행 시계 반대 방향에 기원을 가지고 있으며, 오른쪽이 없습니다. 우리가 각도를 고려하는 경우 a, b그리고 c, 이러한 점에이 수단에 대응 b-a < 180 degrees(의 범위는 0에서 360도에서 각도를 촬영을). 복소수로 angle(B/A)=angle(B)/angle(A). 또한 angle(x) < 180 degrees정확히 반 상반신의 점에 대해서는를 통해 확인 imag(x)>0합니다.

따라서 원점이 AB의 왼쪽에 있는지 여부는로 표현됩니다 (A/B).imag>0. 이것들이 각 사이 클릭 쌍에 대해 모두 같은지 확인하면 A,B,C삼각형 ABC이 원점을 포함 하는지 여부 를 알려줍니다 .

이제 완전 골프 코드로 돌아 갑시다

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

(A-X,B-X,C-X)=(L[0]-X,L[1]-X,L[2]-X)음수 파이썬리스트 인덱스 ( L[-1]= L[2]) 를 이용 하여 각 순환 쌍을에 생성합니다 . Bools 모든 것을 확인하려면 True( 1) 또는 모든 False( 0많은 솔루션이 그랬던 것처럼), 우리는 3으로 그들과 체크 가분성을 추가합니다.


2

포트란 - 232 218 195 174

피의 끔찍한. 이 기능은 데이터가 전달되어 전처리 할 수 ​​없기 때문에 끔찍합니다.

logical function L(x);real::x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4);L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s);endfunction

14 문자의 감소는 테스트 실행에서 함수 이름을 골프화하는 것을 잊었 기 때문입니다. 암묵적인 타이핑과 함수 이름 변경을 잊어 버렸기 때문에 더욱 줄어 듭니다. 다음 20 개의 문자는 단일 배열로 포인트를 읽음으로써 사라졌습니다. 전체 프로그램은

program inTriagle
   real, dimension(2) :: a,b,c,x
   do 
      print*,"Enter coordinates as x,a,b,c"
      read*,x,a,b,c
      if(all(x==0.0).and.all(a==0.0).and.all(b==0.0).and.all(c==0.0)) exit
      print*,"Is point in triangle: ",T(x,a,b,c)
   enddo
 contains!                       
   logical function L(x)
     real::x(8)
     p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3)
     s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4)
     L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s)
   endfunction
end program inTriagle

1
Fortran의 암시 적 타이핑과 8 개의 숫자가 모두 포함 된 단일 입력 배열을 사용하여이 길이를 조금 더 짧게 만들 수 있습니다. logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);o=r*v-u*s;T=ALL([p*(s-v)+q*(u-r)+o,p*v-q*u,q*r-p*s]>=o);end목록 작업을 사용하여이를 더욱 단축하려고했지만 불행히도 잘 작동하지 않았습니다.
Ventero

1
더 일반적인 하위 표현식을 제거하여 더 짧아졌습니다 logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);a=r*v-u*s;b=p*v-q*u;d=q*r-p*s;T=ALL([a-b-d,b,d]>=a);end. 변환에서 실수를하지 않았기를 바랍니다. 원래 코드가 모든 테스트 사례를 통과하지 못하는 것 같습니다.
Ventero

@Ventero : 내가 :( 암시 적 입력을 남용하는 것을 잊었다 믿을 수 없어 감사합니다 당신의 도움을.!
카일 Kanos에게

@ Ventro : 또한, 내 대답은 삼각형의 방향에 달려있는 것 같습니다. TrueOP 의 첫 번째 예 는 원래 방향 을 제공하면서 및 값을 False바꾸면 나타납니다 . BCTrue
Kyle Kanos

아, 실제로, 문제는 (이전 주석의 표기법을 재사용 할 때) 발생 a < 0하여 테스트 해야하는 조건을 효과적으로 반전시킵니다. 불행히도 이것은 안에 모든 것을 감싸서 고칠 수 없으며 abs, 암시 적 조건 bd같은 부호를 a잃어 버릴 수 있습니다. 이것은 (내 마지막 주석의 표기법 및 미리 정의 된 변수를 다시 사용) 같은 것을 사용하여 e=a-b-d;T=ALL([a*a-b*b,a*a-d*d,a*a-e*e,a*b,a*d,a*e]>=0)해결할 수 있습니다. 아마도 더 골프를 칠 수 있습니다.
Ventero

2

MATLAB : 9!

여기에 글을 쓰는 사람은 많지 않습니다.

inpolygon

다음과 같이 호출 할 수 있습니다.

inpolygon(2/3, 2/3, [0 1 1], [0 0 1])

이름이 지정된 변수에 출력이 할당됩니다 ans


실제로 함수를 작성해야한다면 최적화되었을 수 있습니다.

function y=f(a,b,c,d)
inpolygon(a,b,c,d)

2
함수 핸들을 사용하여 더 짧을 수 있습니다.f=@(a,b,c,d)inpolygon(a,b,c,d)
jpjacobs

2

C # 218 (149?)

using P=System.Drawing.PointF;
bool F(P[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}P[]a=new P[3];Array.Copy(p,1,a,0,3);var g=new System.Drawing.Drawing2D.GraphicsPath();g.AddLines(a);return g.IsVisible(p[0]);}

아마도 수학적 방법만큼 문자 효율적이지는 않지만 라이브러리를 재미있게 사용합니다. 또한 느리게 느려집니다.

또한 "숫자 안정성 또는 부동 소수점 정밀도에 대해 걱정할 필요가 없습니다." -불행히도 내부적으로 s를 GraphicsPath사용 int하므로 -1 <f <1 범위의 값은 가능한 세 가지 값만 가질 수 있습니다. float는 7 자리의 정밀도 만 갖기 때문에 1e7을 곱하여 정수로 바꿉니다. 흠, 실제로 정밀도를 잃지 않는 것 같아요 . 또한 다른 방법으로도 악용 될 수 있습니다. 아마도 정확성을 무시하고 "틀린"대답을 받았을 수도 있습니다.

경우 I 가져 오기 라이브러리의 문자 비용, 무시 할 수있어 149 (아주 최소한을, System.Linq그리고 System.Drawing대부분의 윈폼 프로젝트에 꽤 표준이지만, System.Drawing.Drawing2D스트레칭의 비트 수 있습니다) :

bool G(PointF[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}var g=new GraphicsPath();g.AddLines(p.Skip(1).ToArray());return g.IsVisible(p[0]);}

테스트 프로그램 (예, 추악합니다) :

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using P=System.Drawing.PointF;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Program prog = new Program();
        foreach (string test in
@"[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]".Split('\n'))
        {
            string t = test.Replace("[(", "").Replace(")]", "");
            string[] points = t.Split(new string[] { "), (" }, StringSplitOptions.None);

            string[] p = points[0].Split(',');
            P[] xabc = new P[4];

            for (int i = 0; i < 4; i++)
            {
                p = points[i].Split(',');
                xabc[i] = new F(float.Parse(p[0]), float.Parse(p[1]));
            }

            Console.WriteLine(test + "=>" + prog.F(xabc));
        }

        Console.ReadKey();
    }

    bool G(PointF[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }

    bool F(P[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new System.Drawing.Drawing2D.GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }
}

귀엽고 그리기 엔진이 작업을 수행하게합니다.
xnor

2

하스켈 - 233 127

여기에 설명 된대로 교차 제품 사용 :

h(a,b)(p,q)(r,s)(t,u)=z a b p q r s==z a b r s t u&&z a b r s t u==z a b t u p q where z j k l m n o =(o-m)*(j-l)+(l-n)*(k-m)>0

이전의 솔루션은 무게 중심 좌표 와이 스택 교환 답변에 설명 된 수식을 사용하여 구현 되었습니다 .

g(p,q)(r,s)(t,u)(v,w)=
 let (j,k)=(p+(-r),q+(-s))
     (l,m)=(t+(-r),u+(-s))
     (n,o)=(v+(-r),w+(-s))
     d=l*o-n*m
     a=(j*(m-o)+k*(n-l)+l*o-n*m)/d
     b=(j*o-k*n)/d
     c=(k*l-j*m)/d
 in (0<=a&&a<1)&&(0<=b&&b<1)&&(0<=c&&c<1)

두 함수 g와는 h점이 포함하고 삼각형의 꼭지점의 좌표가되는 나머지 테스트 할 첫 번째 네 개의 쌍을 취할.

샘플 입력으로 테스트하려면

let trueTestCases =
  [((-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)),
   ((-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)),
   ((0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)),
   ((-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)),
   ((0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)),
   ((-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)),
   ((-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)),
   ((-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)),
   ((0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)),
   ((-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832))]

let falseTestCases =
  [((-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)),
   ((0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)),
   ((0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)),
   ((0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)),
   ((0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)),
   ((-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)),
   ((-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)),
   ((0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)),
   ((0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)),
   ((0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192))]

type Point = (Double, Double)

test :: [(Point, Point, Point, Point)] -> [Bool]
test testCases =
  map (\((px,py),(ax,ay),(bx,by),(cx,cy)) -> h (px,py) (ax,ay) (bx,by) (cx,cy)) testCases

test trueTestCases --> [True,True,True,True,True,True,True,True,True,True]
test falseTestCases --> [False,False,False,False,False,False,False,False,False,False]

Ungolfed 솔루션 :

type Point = (Double, Double)

-- using cross products

triangulate' (a, b) (p, q) (r, s) (t, u) =
  (side a b p q r s == side a b r s t u) && (side a b r s t u == side a b t u p q)
  where side j k l m n o = (o - m) * (j - l) + (-n + l) * (k - m) >= 0

-- using barycentric coordinates

triangulate :: (Point, Point, Point, Point) -> Bool
triangulate ((px, py), (ax, ay), (bx, by), (cx, cy)) = 
  let (p'x, p'y) = (px + (-ax), py + (-ay))
      (b'x, b'y) = (bx + (-ax), by + (-ay))
      (c'x, c'y) = (cx + (-ax), cy + (-ay))
      d = b'x * c'y - c'x * b'y
      a = (p'x * (b'y - c'y) + p'y * (c'x - b'x) + b'x * c'y - c'x * b'y) / d
      b = (p'x * c'y - p'y * c'x) / d
      c = (p'y * b'x - p'x * b'y) / d
  in
      (0 <= a && a < 1) && (0 <= b && b < 1) && (0 <= c && c < 1)

2

자바 스크립트 (ES6) 120

C=(p,q,i,j,k,l,m,n,
 z=j*(m-k)+i*(l-n)+k*n-l*m,
 s=(j*m-i*n+(n-j)*p+(i-m)*q)/z,
 t=(i*l-j*k+(j-l)*p+(k-i)*q)/z
)=>s>0&t>0&s+t<1

이 다른 질문에 대한 답변에서 직접 복사

FireFox / FireBug 콘솔에서 테스트

모든 1을 출력

;[
C(-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633),
C(-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468),
C(0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497),
C(-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334),
C(0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028),
C(-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683),
C(-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618),
C(-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374),
C(0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519),
C(-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832)
]

모든 0을 출력

;[
C(-0.99103, 0.43842,0.78128, -0.10985,-0.84714, -0.20558,-0.08925, -0.78608),
C(0.15087, -0.56212,-0.87374, -0.3787,0.86403, 0.60374,0.01392, 0.84362),
C(0.1114, 0.66496,-0.92633, 0.27408,0.92439, 0.43692,0.8298, -0.29647),
C(0.87786, -0.8594,-0.42283, -0.97999,0.58659, -0.327,-0.22656, 0.80896),
C(0.43525, -0.8923,0.86119, 0.78278,-0.01348, 0.98093,-0.56244, -0.75129),
C(-0.73365, 0.28332,0.63263, 0.17177,-0.38398, -0.43497,-0.31123, 0.73168),
C(-0.57694, -0.87713,-0.93622, 0.89397,0.93117, 0.40775,0.2323, -0.30718),
C(0.91059, 0.75966,0.60118, 0.73186,0.32178, 0.88296,-0.90087, -0.26367),
C(0.3463, -0.89397,0.99108, 0.13557,0.50122, -0.8724,0.43385, 0.00167),
C(0.88121, 0.36469,-0.29829, 0.21429,0.31395, 0.2734,0.43267, -0.78192)
]

2

SmileBASIC, (111) 100 자

DEF T X,Y,A,B,C,D,E,F
Q=9e5GCLS
GTRI(A-X)*Q,Q*(B-Y),Q*(C-X),Q*(D-Y),Q*(E-X),Q*(F-Y)?!!GSPOIT(0,0)END

삼각형을 그리고 점에서 픽셀의 색상을 확인합니다. 삼각형의 배율은 99999x로 증가하고 이동하여 확인할 지점이 (0,0)이되어 정밀도 손실을 최소화합니다.


2

인텔 8087 FPU 어셈블리, 222 220 바이트

8087 FPU 하드웨어 만 사용하여 계산합니다. 다음은 MACRO로서의 어셈블되지 않은 (이 경우에도 해결되지 않은) 버전입니다 (220 16 진 바이트 코드를 절약 할 것입니다).

; calculate the area of of a triangle ABC using determinate
; input: coordinates (float), Ax,Ay,Bx,By,Cx,Cy
; output: area in ST
TAREA   MACRO   A1,A2,B1,B2,C1,C2
    FLD  A1
    FLD  B2
    FLD  C2
    FSUB        ; ST = By - Cy
    FMUL        ; ST = Ax * ( By - Cy )
    FLD  B1 
    FLD  C2
    FLD  A2
    FSUB        ; ST = Cy - Ay
    FMUL        ; ST = Bx * ( Cy - Ay )
    FLD  C1
    FLD  A2
    FLD  B2
    FSUB        ; Ay - By
    FMUL        ; Cx * ( Ay - By )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay ) + Ax * ( By - Cy )
    FLD1        ; make a value of 2
    FADD ST,ST  ; ST = 2
    FDIV        ; divide by 2
    FABS        ; take abs value
        ENDM

; determine if point X is in triangle ABC
; input: points X, A, B, C
; output: ZF=1 if X in triangle, ZF=0 if X not in triangle
TXINABC     MACRO X1,X2,A1,A2,B1,B2,C1,C2

    TAREA  A1,A2,B1,B2,C1,C2    ; ST(3) = area of triangle ABC
    TAREA  X1,X2,B1,B2,C1,C2    ; ST(2) = area of triangle XBC
    TAREA  A1,A2,X1,X2,C1,C2    ; ST(1) = area of triangle AXC
    TAREA  A1,A2,B1,B2,X1,X2    ; ST(0) = area of triangle ABX

    FADD        ; add areas of triangles with point
    FADD        ; ST = ST + ST(1) + ST(2)
    FCOMPP      ; compare ST to ST(1) and pop results
    FWAIT       ; sync CPU/FPU
    FSTSW R     ; store result flags to R
    MOV  AX, R  ; move result to AX
    SAHF        ; store result into CPU flags for conditional check
        ENDM

설명

determinate를 사용하여 ABC ​​삼각형의 면적을 계산 한 다음 X 점과 ABC 삼각형의 다른 두 점으로 형성된 삼각형을 계산합니다. 삼각형 ABC의 면적이 삼각형 XBC + AXC + ABX의 면적 합과 같으면 점은 삼각형 내에 있습니다. 결과는 ZF로 반환됩니다.

이것에 대해 깔끔한 것

모든 수학 및 부동 소수점 연산은 80 비트 확장 정밀도를 가진 하드웨어에서 수행됩니다. 최종 부동 소수점 비교는 하드웨어에서도 수행되므로 매우 정확합니다.

또한 한 번에 8 개의 8087 스택 레지스터를 모두 사용합니다.

이것에 대해 깔끔하지 않은 것

삼각형의 점은 계산 중에 수식에 여러 번 다시 연결되어야하므로 메모리의 각 변수를 FPU의 스택 레지스터에 올바른 순서로 한 번에 하나씩로드해야합니다. 이것은 MACRO로서의 기능처럼 상당히 쉽게 모델링 될 수 있지만, 이는 코드가 어셈블리에서 확장 될 때마다 확장되어 중복 코드를 생성 함을 의미합니다. 동일한 반복 코드 세그먼트 중 일부를 PROC로 이동하여 41 바이트가 절약되었습니다. 그러나 코드를 읽기 어렵게하므로 위의 목록에없는 코드입니다 ( "ungolfed"로 레이블이 지정된 이유).

테스트

다음은 출력을 보여주는 IBM DOS를 사용하는 테스트 프로그램입니다.

TTEST   MACRO T
        LOCAL IS_IN_TRI

    TXINABC T,T+4*1,T+4*2,T+4*3,T+4*4,T+4*5,T+4*6,T+4*7
    MOV  DX, OFFSET TEQ     ; load true string by default 
    JZ   IS_IN_TRI          ; if ZF=1, it is in triangle, skip to display
    MOV  DX, OFFSET FEQ     ; otherwise ZF=0 means not in triangle, so load false string
IS_IN_TRI:
    MOV  AH, 9              ; DOS write string function
    INT  21H 
        ENDM

START:
    FINIT                   ; reset 8087

    TTEST   T0              ; true tests
    TTEST   T1
    TTEST   T2
    TTEST   T3
    TTEST   T4
    TTEST   T5
    TTEST   T6
    TTEST   T7
    TTEST   T8
    TTEST   T9

    TTEST   F0              ; false tests
    TTEST   F1
    TTEST   F2
    TTEST   F3
    TTEST   F4
    TTEST   F5
    TTEST   F6  
    TTEST   F7
    TTEST   F8  
    TTEST   F9

    RET         ; return to DOS

T0  DD  -0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633
T1  DD  -0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468
T2  DD  0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497
T3  DD  -0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334
T4  DD  0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028
T5  DD  -0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683
T6  DD  -0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618
T7  DD  -0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374
T8  DD  0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519
T9  DD  -0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832

F0  DD  -0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608
F1  DD  0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362
F2  DD  0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647
F3  DD  0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896
F4  DD  0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129
F5  DD  -0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168
F6  DD  -0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718
F7  DD  0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367
F8  DD  0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167
F9  DD  0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192

TEQ DB 'In Triangle',0DH,0AH,'$'
FEQ DB 'Not In Triangle',0DH,0AH,'$'

산출

In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle

1

C 414 (기존 465)

골프

#define D double 
int F(D ax,D ay,D bx,D by,D cx,D cy,D px,D py){int y=0;double J,K;D m=(ax-bx<0.001)?(by-ay)/(ax-bx):1000;D b=m*ax+ay;J=m*cx-cy+b;K=m*px-py+b;if(J*K>=0)y=1;return y;}D T[8],k;int i,n;void G(){while(i<8){scanf("%lf",&k);T[i++]=k;}n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);printf(n==3?"True":"False");}

설명을 위해 원래 함수 선언 추가

/**
* determine if points C & P are on same side of line AB
* return 1 if true, 0 otherwise
*/
int PointsSameSide(D ax,D ay,D bx,D by,D cx, D cy, D px, D py);

명명 된 함수로 다시 작성 : 각 줄마다 stdin을 통해 입력하거나 공백으로 구분 된 한 줄로 입력합니다.

#define D double
int F(D ax,D ay,D bx,D by,D cx, D cy, D px, D py)
{
int y=0;
double J,K;
D m = (ax-bx<0.001)?(by-ay)/(ax-bx):1000;
D b = m*ax+ay;
J=m*cx-cy+b;
K=m*px-py+b;
if(J*K>=0)y=1;
return y;
}
double T[8],k;
int i,n;
void G()
{
while(i<8){scanf("%lf",&k);T[i++]=k;}
n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);
n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);
n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);
printf(n==3?"True":"False");
}

3
줄 바꿈과 불필요한 공백을 제거하여 바이트를 절약 할 수 있습니다. 또한로 double정의 D되었지만 double코드에서 계속 사용 합니다.
gronostaj

1

자바, 149 자

g=Math.atan2(100*(d-y),(a-x));h=Math.atan2(100*(e-y),(b-x));i=Math.atan2(100*(f-y),(c-x));k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;

"Math"라고 써야한다고 끔찍합니다. 매번. 이것은 실제 프로그램입니다 :

package mathPackage;
public class InTriangle {
public static void main(String[] args) {
    boolean k;
    double a=-1,b=0,c=1,d=0,e=1,f=0,x=0,y=0.4;
    double g,h,i;
    g=Math.atan2(100*(d-y),(a-x));
    h=Math.atan2(100*(e-y),(b-x));
    i=Math.atan2(100*(f-y),(c-x));
    k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;
    System.out.println(k);
    System.out.println(g);
    System.out.println(h);
    System.out.println(i);
    System.out.print(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g));
}
}

여기서 a는 x의 점 a, b는 x의 점 b, c는 x의 c, d는 y의 a, e는 y의 b, f는 c의 y, x와 y는 x이고 요점. 부울 k는 그것이 참인지 아닌지를 결정합니다.


1
무엇입니까 100*?
xnor

1

자바 스크립트 125/198

8 개의 인수로 포인트가 제공되는 경우 :

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

점이 2 차원 배열로 제공되는 경우 :

function c(s){return (z(s[1][0],s[1][1],s[2][0],s[2][1])+z(s[2][0],s[2][1],s[3][0],s[3][1])+z(s[3][0],s[3][1],s[1][0],s[1][1]))%3<1;function z(a,b,c,d){return (s[0][1]-b)*(c-a)-(s[0][0]-a)*(d-b)>0}}

이 코드는 멋진 벡터 수학을 사용하지 않습니다. 대신 점이 삼각형 안에 있는지 여부를 확인하기 위해 간단한 대수 기법 만 사용합니다. 공식 :

(y-b)(c-a) - (x-a)(d-b)

이것은 점이 선의 어느쪽에 있는지를 나타내며 기울기 정의를 재정렬하여 파생됩니다.

            m = (y2-y1)/(x2-x1)
      (y2-y1) = m(x2-x1)
       (y-y1) = m(x-x1)     ,substituting point we are testing (x,y) to be the 2nd point
       (y-y1) = (x-x1)(y2-y1)/(x2-x1)  ,substitute back the original definition of m
(y-y1)(x2-x1) = (x-x1)(y2-y1)    <-- left side will be greater than the right side, if
                                     the point is on the left; otherwise, it's on the right
            0 = (y-b)(c-a)-(x-a)(d-b) ,where (a,b)=(x1,y1), (c,d)=(x2,y2)

3면을 모두 테스트하면 삼각형 주위에서 점을 테스트하기 때문에 점이 삼각형 안에있을 때만 3이 모두 같은 부호를 가진 숫자를 산출해야합니다. 점이 측면에 있으면 테스트 중 하나가 0을 반환해야합니다.

jsFiddle 테스트 코드 : http://jsfiddle.net/DerekL/zEzZU/

var l = [[-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633],[-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468],[0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497],[-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334],[0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028],[-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683],[-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618],[-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374],[0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519],[-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832],
         [-0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608],[0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362],[0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647],[0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896],[0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129],[-0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168],[-0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718],[0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367],[0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167],[0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192]];

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

for(var i = 0; i < l.length; i++){
    console.log(d.apply(undefined,l[i]));    //10 true, 10 false
}

CoffeeScript로 변환하면 97 자 (공백 또는 탭 제외)가 계산됩니다.

d=(x,y,a,b,c,d,e,f)->
    z=(a,b,c,d)->
        (y-b)*(c-a)-(x-a)*(d-b)>0
    (z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1

ES6로 변환 된 경우 115 자 :

d=(x,y,a,b,c,d,e,f)=>{z=(a,b,c,d)=>{return (y-b)*(c-a)-(x-a)*(d-b)>0};return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

이다 D (안 그래도 몇 가지 다른 접근 좌표 무게 중심 공상했다) : 내가 사용은 "멋진 벡터 수학". 최고 투표 답변과 마찬가지로 ES6을 사용하고 같은 기능을 정의하여 몇 바이트를 절약 할 수 있습니다 d=(x,y,...)=>{...}. pastebin.com/RVFk1D5k ... 필요하지 않은 CoffeeScript를 사용하여 더 많은 비용을 절약 할 수 있습니다 return. 어쨌든 대신 대신 1 바이트를 저장할 수 있습니다 . <1==0
마틴 엔더

@ m.buettner : o 내가 사용한 방정식이 벡터와 관련이 없다고 생각했지만 (단순 대수에서 파생) 분명히 같은 방정식을 산출합니다. 수학은 훌륭합니다.
Derek 朕 會 功夫

1

R, 23

MATLAB 에서 영감을 얻은

SDMTools::pnt.in.poly()

length-2 벡터 인 것처럼 호출 SDMTools::pnt.in.poly(point,triangle)되며 꼭짓점의 3x2 행렬입니다. SDMTools는 CRAN에서 사용 가능합니다.pointtriangle


1

수학, 38 자

RegionMember[Polygon[#[[1]]],#[[2]]] &

예:

d = {{{0, 0}, {1, 0}, {.5, .7}}, {.5, .6}};

RegionMember[Polygon[#[[1]]], #[[2]]] & @ d

(* True *)


공백을 문자로 계산하는 것이 표준이지만 아마도 여기서 아무 것도 나누지 않고 공백을 제거 할 수 있습니다.
xnor

1
또한 사전 정의 된 변수를 사용하는 대신 입력을 가져 와서 출력해야합니다. Mathematica 답변을 검색하여 어떻게 수행하는지 확인할 수 있습니다.
xnor

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.