// File: /workspace/github_cpp_makefile_star2_O1/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 $0x38, %rsp
movq %rdx, %r14
movq %rdi, %rbx
testq %rdx, %rdx
je 0x27d53
movl $0xffffffff, (%r14)     # imm = 0xFFFFFFFF
movsd 0x58(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0xa0(%rbx), %xmm1
movsd %xmm1, 0x10(%rsp)
movsd (%rsi), %xmm0
movsd 0x8(%rsi), %xmm2
movsd %xmm2, 0x18(%rsp)
divsd %xmm1, %xmm0
callq 0x71c0
movsd 0x10(%rsp), %xmm1
mulsd %xmm1, %xmm0
movapd %xmm0, 0x20(%rsp)
movsd 0x18(%rsp), %xmm0
divsd %xmm1, %xmm0
callq 0x71c0
movsd 0x10(%rsp), %xmm6
movapd 0x20(%rsp), %xmm15
movapd %xmm6, %xmm1
divsd 0x17324(%rip), %xmm1    # 0x3f0e0
movsd 0x8(%rsp), %xmm2
subsd %xmm1, %xmm2
xorl %eax, %eax
ucomisd %xmm15, %xmm2
ja 0x281b6
mulsd %xmm6, %xmm0
movsd 0x60(%rbx), %xmm2
subsd %xmm1, %xmm2
ucomisd %xmm0, %xmm2
ja 0x281b6
movsd 0x68(%rbx), %xmm2
addsd %xmm1, %xmm2
ucomisd %xmm2, %xmm15
ja 0x281b6
addsd 0x70(%rbx), %xmm1
ucomisd %xmm1, %xmm0
ja 0x281b6
movq 0x10(%rbx), %rcx
movsd (%rcx), %xmm2
movsd 0x8(%rcx), %xmm9
movapd %xmm2, %xmm4
subsd %xmm15, %xmm4
movapd 0x17204(%rip), %xmm3    # 0x3f030
andpd %xmm3, %xmm4
movapd %xmm9, %xmm5
subsd %xmm0, %xmm5
andpd %xmm3, %xmm5
addsd %xmm4, %xmm5
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
ucomisd %xmm5, %xmm6
ja 0x281b6
movslq 0x8(%rbx), %rax
cmpq $0x2, %rax
setge %dl
jl 0x28037
movsd 0x1727f(%rip), %xmm4    # 0x3f0e8
movapd %xmm6, %xmm1
mulsd %xmm6, %xmm4
leaq 0x18(%rcx), %rdi
leaq -0x1(%rax), %r8
xorl %esi, %esi
movapd 0x171ad(%rip), %xmm5    # 0x3f030
movsd 0x17245(%rip), %xmm6    # 0x3f0d0
movsd 0x17235(%rip), %xmm7    # 0x3f0c8
movapd %xmm2, %xmm8
movsd %xmm9, 0x8(%rsp)
movapd %xmm8, %xmm10
movsd -0x8(%rdi), %xmm8
movapd %xmm8, %xmm11
subsd %xmm15, %xmm11
andpd %xmm5, %xmm11
ucomisd %xmm11, %xmm4
jbe 0x27eda
movsd (%rdi), %xmm11
subsd %xmm0, %xmm11
andpd %xmm5, %xmm11
ucomisd %xmm11, %xmm4
ja 0x2803b
ucomisd %xmm10, %xmm8
jae 0x27f12
movapd %xmm8, %xmm11
addsd %xmm6, %xmm11
movapd %xmm10, %xmm12
addsd %xmm7, %xmm12
cmplepd %xmm15, %xmm11
movapd %xmm15, %xmm13
cmplepd %xmm12, %xmm13
andpd %xmm11, %xmm13
movd %xmm13, %r9d
jmp 0x27f41
movapd %xmm10, %xmm11
addsd %xmm6, %xmm11
movapd %xmm8, %xmm12
addsd %xmm7, %xmm12
movapd %xmm15, %xmm13
cmplepd %xmm12, %xmm13
cmplepd %xmm15, %xmm11
andpd %xmm13, %xmm11
movd %xmm11, %r9d
testb $0x1, %r9b
je 0x28014
movsd (%rdi), %xmm11
ucomisd %xmm9, %xmm11
jae 0x27f88
movapd %xmm11, %xmm12
addsd %xmm6, %xmm12
movapd %xmm9, %xmm13
addsd %xmm7, %xmm13
cmplepd %xmm0, %xmm12
movapd %xmm0, %xmm14
cmplepd %xmm13, %xmm14
andpd %xmm12, %xmm14
movd %xmm14, %r9d
jmp 0x27fb7
movapd %xmm9, %xmm12
addsd %xmm6, %xmm12
movapd %xmm11, %xmm13
addsd %xmm7, %xmm13
movapd %xmm0, %xmm14
cmplepd %xmm13, %xmm14
cmplepd %xmm0, %xmm12
andpd %xmm14, %xmm12
movd %xmm12, %r9d
testb $0x1, %r9b
je 0x28014
movapd %xmm8, %xmm12
subsd %xmm10, %xmm12
subsd %xmm9, %xmm11
movapd %xmm15, %xmm13
subsd %xmm10, %xmm13
movapd %xmm0, %xmm10
subsd %xmm9, %xmm10
mulsd %xmm12, %xmm10
mulsd %xmm11, %xmm13
subsd %xmm10, %xmm13
andpd %xmm3, %xmm12
andpd %xmm3, %xmm11
addsd %xmm12, %xmm11
addsd %xmm11, %xmm11
andpd %xmm3, %xmm13
mulsd %xmm1, %xmm11
ucomisd %xmm13, %xmm11
ja 0x28044
movsd (%rdi), %xmm9
leaq 0x2(%rsi), %rdx
cmpq %rax, %rdx
setb %dl
incq %rsi
addq $0x10, %rdi
cmpq %rsi, %r8
jne 0x27e9f
xorl %eax, %eax
jmp 0x2804e
xorl %eax, %eax
jmp 0x28055
movl $0xfffffffe, %eax       # imm = 0xFFFFFFFE
subl %esi, %eax
jmp 0x2804e
xorl %eax, %eax
testq %r14, %r14
je 0x2804e
movl %esi, (%r14)
movsd 0x8(%rsp), %xmm9
testb $0x1, %dl
jne 0x281b6
movslq 0x8(%rbx), %rdx
xorl %eax, %eax
cmpq $0x2, %rdx
jl 0x281b6
leaq -0x1(%rdx), %rsi
movq %rdx, %rdi
addq $-0x2, %rdi
movl %edi, %r8d
leaq 0x20(%rcx), %r9
xorl %eax, %eax
movl $0x1, %r10d
xorpd %xmm3, %xmm3
movapd %xmm9, %xmm4
movapd %xmm4, %xmm5
movapd %xmm2, %xmm6
movsd -0x10(%r9), %xmm2
movsd -0x8(%r9), %xmm4
ucomisd %xmm0, %xmm5
jb 0x280b5
ucomisd %xmm0, %xmm4
ja 0x281a6
ucomisd %xmm5, %xmm0
jb 0x280c5
ucomisd %xmm4, %xmm0
ja 0x281a6
ucomisd %xmm6, %xmm15
jbe 0x280d7
ucomisd %xmm2, %xmm15
ja 0x281a6
ucomisd %xmm0, %xmm4
jne 0x28108
jp 0x28108
cmpq %rsi, %r10
movq %rcx, %r11
cmovlq %r9, %r11
movsd 0x8(%r11), %xmm6
subsd %xmm4, %xmm6
ucomisd %xmm3, %xmm6
jne 0x28170
jp 0x28170
cmpq %rdi, %r10
jge 0x2814d
movsd 0x18(%r9), %xmm6
jmp 0x2816c
ucomisd %xmm5, %xmm4
jne 0x28110
jnp 0x28159
movapd %xmm0, %xmm7
subsd %xmm5, %xmm7
movapd %xmm2, %xmm8
subsd %xmm6, %xmm8
mulsd %xmm7, %xmm8
movapd %xmm4, %xmm7
subsd %xmm5, %xmm7
divsd %xmm7, %xmm8
addsd %xmm6, %xmm8
xorl %r11d, %r11d
testl %eax, %eax
sete %r11b
ucomisd %xmm15, %xmm8
cmovael %r11d, %eax
jmp 0x281a6
cmpq %r10, %r8
jne 0x28167
movapd %xmm9, %xmm6
jmp 0x2816c
xorl %r11d, %r11d
testl %eax, %eax
sete %r11b
movl %r11d, %eax
jmp 0x281a6
movsd 0x18(%rcx), %xmm6
subsd %xmm4, %xmm6
movapd %xmm4, %xmm7
subsd %xmm5, %xmm7
mulsd %xmm6, %xmm7
movapd %xmm15, %xmm5
cmpnlepd %xmm2, %xmm5
xorpd %xmm6, %xmm6
cmpnltpd %xmm7, %xmm6
orpd %xmm5, %xmm6
movd %xmm6, %r11d
xorl %ebx, %ebx
testl %eax, %eax
sete %bl
testb $0x1, %r11b
cmovel %ebx, %eax
incq %r10
addq $0x10, %r9
cmpq %r10, %rdx
jne 0x28091
addq $0x38, %rsp
popq %rbx
popq %r14
retq