// File: /workspace/github_cpp_makefile_star2_O3/thierry7100[P]CutOptim/src/Geometry.cpp
// Function: Polygon::isInPoly(Point const*, int*)
int Polygon::isInPoly(const Point *p, int *SegmentIdx)
{
double lastX, lastY;
int inside = false;

    if ( SegmentIdx != nullptr ) *SegmentIdx = -1;      //  If provided, initialize to - 1 (not on an edge
    //  Round coordinates to avoid errors
    Point lP = Point(round(p->x/precision)*precision, round(p->y/precision)*precision);

    if ( lP.x < BoundingBox.A.x - precision/3 ) return false;       //  Outside bounding box, impossible, sub precision to avoid rounding errors
    if ( lP.y < BoundingBox.A.y - precision/3) return false;       //  Outside bounding box, impossible
    if ( lP.x > BoundingBox.B.x + precision/3) return false;       //  Outside bounding box, impossible
    if ( lP.y > BoundingBox.B.y + precision/3) return false;       //  Outside bounding box, impossible
    //  If the point is a vertex, return false.
    //  Also checks if the point is on one edge, in this case return false
    lastX = _Vertices[0].x;
    lastY = _Vertices[0].y;
    if ( fabs(lastX-lP.x) + fabs(lastY-lP.y) < precision ) return -1;    //  On vertex 0
    for (int i = 1; i < nVertices; i++)
    {
        if ( fabs(_Vertices[i].x-lP.x) < 50*precision && fabs(_Vertices[i].y-lP.y) < 50*precision) return -(i+1);      //  this is a vertex, return negative value
        //  Check if lP is on edge between LastX,LastY and _Vertice[i]
        if ( isBetween(lP.x, lastX, _Vertices[i].x) && isBetween(lP.y, lastY, _Vertices[i].y) )
        {
            //  Could be on edge, check if points are aligned : compute determinant
            double deltaX =_Vertices[i].x - lastX;
            double deltaY =_Vertices[i].y - lastY;
            double det = (lP.x - lastX)*deltaY - (lP.y - lastY)*deltaX;
            //  With infinite precision, the determinant is null when the points are aligned
            //  Here, we don't have infinite precision (rounding)
            //  It could be quite complex to determine the alignment
            //  Say if fabs(det) is lower than precision*fabs(deltaX + deltaY)
            double max_error_det = 2*(fabs(deltaX) + fabs(deltaY));
#define OUTPUT_DETERMINANT 0

#if OUTPUT_DETERMINANT > 0
            if ( fabs(det) < 10 )
                cout << "det =" << det << ", deltaX=" << deltaX << ", deltaY=" << deltaY << ", computed precision=" << max_error_det*precision<< '\n';
#endif // OUTPUT_DETERMINANT
            if ( fabs(det) < max_error_det * precision )
            {
                if ( SegmentIdx != nullptr ) *SegmentIdx = i - 1; //    Between i - 1 and i.
                return false;      //  On edge, not inside !
            }
        }
        lastX = _Vertices[i].x;
        lastY = _Vertices[i].y;
    }

    lastX = _Vertices[0].x;
    lastY = _Vertices[0].y;
    for (int i = 1; i < nVertices; i++)
    {
        double curX = _Vertices[i].x;
        double curY = _Vertices[i].y;
        //  Note the <= comparison with last Y, to avoid double counting when line intersect edge at the vertex.
        if (!(lP.y <= lastY && lP.y < curY))           //   Not below segment so intersect is possible
        {
            if (!(lP.y >= lastY && lP.y > curY))       //  not Above current segment so intersect is possible
            {
                if ( !(lP.x > lastX && lP.x > curX))  //  Not after current segment, so intersect is possible
                {
                    if (curY == lP.y)                   //  Intersect at vertex ?
                    {
                        double DiffY;
                        //  In this case, change inside if H line really cross the edge
                        //  If DiffY is not null (not horizontal) and DiffY has not the same sign as curY-LastY, this is not a true intersection.
                        if ( i < nVertices - 1)
                            DiffY =  _Vertices[i+1].y - curY;
                        else
                            DiffY = _Vertices[0].y - curY;
                        //  If DiffY is null, do the same thing with next point
                        if ( DiffY == 0 )
                        {
                            if ( i < nVertices - 2)
                                DiffY =  _Vertices[i+2].y - curY;
                            else if ( i == nVertices - 2)
                                DiffY = _Vertices[0].y - curY;
                            else
                                DiffY = _Vertices[1].y - curY;
                        }
                        //  In this case intersect only if curY-LastY has the same sign as DiffY
                        double sign = -1;
                        sign = (curY - lastY) * DiffY;
                        if ( sign > 0 && lP.x <= curX )
                            inside = !inside;
                    }
                    else if ( curY != lastY)         //  Only if segment is not horizontal
                    {
                        double intersect = lastX + (lP.y - lastY) * (curX - lastX) / (curY - lastY);
                        if ( lP.x <= intersect )
                            inside = ! inside;
                    }
                    else
                    {
                        inside = !inside;
                    }
                }
            }
        }
        lastX = curX;
        lastY = curY;
    }
    return inside;
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x58, %rsp
movq %rdx, %rbx
movq %rdi, %r14
testq %rdx, %rdx
je 0x2778a
movl $0xffffffff, (%rbx)     # imm = 0xFFFFFFFF
movsd 0x58(%r14), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0xa0(%r14), %xmm2
movapd %xmm2, 0x30(%rsp)
movupd (%rsi), %xmm0
unpcklpd %xmm2, %xmm2            # xmm2 = xmm2[0,0]
movapd %xmm2, 0x40(%rsp)
divpd %xmm2, %xmm0
movapd %xmm0, 0x10(%rsp)
callq 0x71c0
movapd %xmm0, 0x20(%rsp)
movapd 0x10(%rsp), %xmm0
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
callq 0x71c0
movapd 0x30(%rsp), %xmm15
movapd 0x20(%rsp), %xmm14
unpcklpd %xmm0, %xmm14           # xmm14 = xmm14[0],xmm0[0]
mulpd 0x40(%rsp), %xmm14
movapd %xmm15, %xmm1
divsd 0x1687a(%rip), %xmm1    # 0x3e078
movsd 0x8(%rsp), %xmm0
subsd %xmm1, %xmm0
xorl %eax, %eax
ucomisd %xmm14, %xmm0
ja 0x27ba0
movsd 0x60(%r14), %xmm2
subsd %xmm1, %xmm2
movapd %xmm14, %xmm0
unpckhpd %xmm14, %xmm0           # xmm0 = xmm0[1],xmm14[1]
ucomisd %xmm0, %xmm2
ja 0x27ba0
movsd 0x68(%r14), %xmm2
addsd %xmm1, %xmm2
ucomisd %xmm2, %xmm14
ja 0x27ba0
addsd 0x70(%r14), %xmm1
ucomisd %xmm1, %xmm0
ja 0x27ba0
movq 0x10(%r14), %rcx
movupd (%rcx), %xmm1
movapd %xmm1, %xmm2
subpd %xmm14, %xmm2
andpd 0x167bf(%rip), %xmm2    # 0x3e030
pshufd $0xee, %xmm2, %xmm3     # xmm3 = xmm2[2,3,2,3]
addsd %xmm2, %xmm3
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
ucomisd %xmm3, %xmm15
ja 0x27ba0
movslq 0x8(%r14), %rdx
movl $0x0, %eax
cmpq $0x2, %rdx
jl 0x27ba0
movsd 0x167db(%rip), %xmm3    # 0x3e080
mulsd %xmm15, %xmm3
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
leaq 0x18(%rcx), %rax
leaq -0x1(%rdx), %rdi
xorl %esi, %esi
movapd 0x1676c(%rip), %xmm4    # 0x3e030
movsd 0x167bc(%rip), %xmm5    # 0x3e088
movsd 0x1678c(%rip), %xmm6    # 0x3e060
movapd 0x16754(%rip), %xmm7    # 0x3e030
movapd %xmm1, %xmm8
movapd %xmm2, %xmm9
movapd %xmm8, %xmm10
movsd -0x8(%rax), %xmm8
movapd %xmm8, %xmm11
subsd %xmm14, %xmm11
andpd %xmm4, %xmm11
ucomisd %xmm11, %xmm3
jbe 0x27921
movsd (%rax), %xmm11
subsd %xmm0, %xmm11
andpd %xmm4, %xmm11
ucomisd %xmm11, %xmm3
ja 0x27b8e
ucomisd %xmm10, %xmm8
jae 0x27953
movapd %xmm8, %xmm11
addsd %xmm5, %xmm11
movapd %xmm10, %xmm12
addsd %xmm6, %xmm12
ucomisd %xmm14, %xmm12
jb 0x27a2e
ucomisd %xmm11, %xmm14
jae 0x2797d
jmp 0x27a2e
movapd %xmm10, %xmm11
addsd %xmm5, %xmm11
ucomisd %xmm11, %xmm14
movapd %xmm8, %xmm11
addsd %xmm6, %xmm11
jb 0x27a2e
ucomisd %xmm14, %xmm11
jb 0x27a2e
movsd (%rax), %xmm11
ucomisd %xmm9, %xmm11
jae 0x279b1
movapd %xmm11, %xmm12
addsd %xmm5, %xmm12
movapd %xmm9, %xmm13
addsd %xmm6, %xmm13
ucomisd %xmm0, %xmm13
jb 0x27a2e
ucomisd %xmm12, %xmm0
jae 0x279d3
jmp 0x27a2e
movapd %xmm9, %xmm12
addsd %xmm5, %xmm12
ucomisd %xmm12, %xmm0
movapd %xmm11, %xmm12
addsd %xmm6, %xmm12
jb 0x27a2e
ucomisd %xmm0, %xmm12
jb 0x27a2e
movapd %xmm8, %xmm12
subsd %xmm10, %xmm12
subsd %xmm9, %xmm11
movapd %xmm14, %xmm13
subsd %xmm10, %xmm13
movapd %xmm0, %xmm10
subsd %xmm9, %xmm10
mulsd %xmm12, %xmm10
mulsd %xmm11, %xmm13
subsd %xmm10, %xmm13
andpd %xmm7, %xmm12
andpd %xmm7, %xmm11
addsd %xmm12, %xmm11
addsd %xmm11, %xmm11
andpd %xmm7, %xmm13
mulsd %xmm15, %xmm11
ucomisd %xmm13, %xmm11
ja 0x27b97
movsd (%rax), %xmm9
incq %rsi
addq $0x10, %rax
cmpq %rsi, %rdi
jne 0x278e6
xorl %eax, %eax
cmpl $0x2, %edx
jl 0x27ba0
leal -0x1(%rdx), %esi
leal -0x2(%rdx), %edi
leaq 0x20(%rcx), %r8
xorl %eax, %eax
movl $0x1, %r9d
xorpd %xmm3, %xmm3
movapd %xmm2, %xmm4
movapd %xmm4, %xmm5
movapd %xmm1, %xmm6
movsd -0x10(%r8), %xmm1
movsd -0x8(%r8), %xmm4
ucomisd %xmm0, %xmm5
jb 0x27a8c
ucomisd %xmm0, %xmm4
ja 0x27b7c
ucomisd %xmm5, %xmm0
jb 0x27a9c
ucomisd %xmm4, %xmm0
ja 0x27b7c
ucomisd %xmm6, %xmm14
jbe 0x27aae
ucomisd %xmm1, %xmm14
ja 0x27b7c
ucomisd %xmm0, %xmm4
jne 0x27adf
jp 0x27adf
cmpq %rsi, %r9
movq %rcx, %r10
cmovbq %r8, %r10
movsd 0x8(%r10), %xmm6
subsd %xmm4, %xmm6
ucomisd %xmm3, %xmm6
jne 0x27b43
jp 0x27b43
cmpq %rdi, %r9
jae 0x27b24
movsd 0x18(%r8), %xmm6
jmp 0x27b3f
ucomisd %xmm5, %xmm4
jne 0x27ae7
jnp 0x27b2c
movapd %xmm0, %xmm7
subsd %xmm5, %xmm7
movapd %xmm1, %xmm8
subsd %xmm6, %xmm8
mulsd %xmm7, %xmm8
movapd %xmm4, %xmm7
subsd %xmm5, %xmm7
divsd %xmm7, %xmm8
addsd %xmm6, %xmm8
xorl %r10d, %r10d
testl %eax, %eax
sete %r10b
ucomisd %xmm14, %xmm8
cmovael %r10d, %eax
jmp 0x27b7c
jne 0x27b3a
movapd %xmm2, %xmm6
jmp 0x27b3f
xorl %r10d, %r10d
testl %eax, %eax
sete %r10b
movl %r10d, %eax
jmp 0x27b7c
movsd 0x18(%rcx), %xmm6
subsd %xmm4, %xmm6
movapd %xmm4, %xmm7
subsd %xmm5, %xmm7
mulsd %xmm6, %xmm7
movapd %xmm14, %xmm5
cmpnlepd %xmm1, %xmm5
xorpd %xmm6, %xmm6
cmpnltpd %xmm7, %xmm6
orpd %xmm5, %xmm6
movd %xmm6, %r10d
xorl %r11d, %r11d
testl %eax, %eax
sete %r11b
testb $0x1, %r10b
cmovel %r11d, %eax
incq %r9
addq $0x10, %r8
cmpq %r9, %rdx
jne 0x27a68
jmp 0x27ba0
movl $0xfffffffe, %eax       # imm = 0xFFFFFFFE
subl %esi, %eax
jmp 0x27ba0
xorl %eax, %eax
testq %rbx, %rbx
je 0x27ba0
movl %esi, (%rbx)
addq $0x58, %rsp
popq %rbx
popq %r14
retq