// File: 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 %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xa8(%rbp)
movl $0x0, -0x34(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x60a4a
movq -0x20(%rbp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movq -0xa8(%rbp), %rax
movq -0x18(%rbp), %rcx
movsd (%rcx), %xmm0
divsd 0xa0(%rax), %xmm0
callq 0x9220
movq -0xa8(%rbp), %rax
mulsd 0xa0(%rax), %xmm0
movsd %xmm0, -0xb0(%rbp)
movq -0x18(%rbp), %rcx
movsd 0x8(%rcx), %xmm0
divsd 0xa0(%rax), %xmm0
callq 0x9220
movq -0xa8(%rbp), %rax
movaps %xmm0, %xmm1
movsd -0xb0(%rbp), %xmm0
mulsd 0xa0(%rax), %xmm1
leaq -0x48(%rbp), %rdi
callq 0x5b520
movq -0xa8(%rbp), %rax
movsd -0x48(%rbp), %xmm1
movsd 0x58(%rax), %xmm0
movsd 0xa0(%rax), %xmm2
movsd 0x23629(%rip), %xmm3    # 0x84100
divsd %xmm3, %xmm2
subsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x60af1
movl $0x0, -0x4(%rbp)
jmp 0x61242
movq -0xa8(%rbp), %rax
movsd -0x40(%rbp), %xmm1
movsd 0x60(%rax), %xmm0
movsd 0xa0(%rax), %xmm2
movsd 0x235ee(%rip), %xmm3    # 0x84100
divsd %xmm3, %xmm2
subsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x60b2c
movl $0x0, -0x4(%rbp)
jmp 0x61242
movq -0xa8(%rbp), %rax
movsd -0x48(%rbp), %xmm0
movsd 0x68(%rax), %xmm1
movsd 0xa0(%rax), %xmm2
movsd 0x235b3(%rip), %xmm3    # 0x84100
divsd %xmm3, %xmm2
addsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x60b67
movl $0x0, -0x4(%rbp)
jmp 0x61242
movq -0xa8(%rbp), %rax
movsd -0x40(%rbp), %xmm0
movsd 0x70(%rax), %xmm1
movsd 0xa0(%rax), %xmm2
movsd 0x23578(%rip), %xmm3    # 0x84100
divsd %xmm3, %xmm2
addsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x60ba2
movl $0x0, -0x4(%rbp)
jmp 0x61242
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x63990
movq -0xa8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x28(%rbp)
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x63990
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movsd 0x8(%rcx), %xmm0
movsd %xmm0, -0x30(%rbp)
movsd -0x28(%rbp), %xmm1
subsd -0x48(%rbp), %xmm1
movaps 0x234b8(%rip), %xmm0    # 0x840b0
pand %xmm0, %xmm1
movsd -0x30(%rbp), %xmm0
subsd -0x40(%rbp), %xmm0
movaps 0x234a3(%rip), %xmm2    # 0x840b0
pand %xmm2, %xmm0
addsd %xmm0, %xmm1
movsd 0xa0(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x60c2f
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x61242
movl $0x1, -0x4c(%rbp)
movq -0xa8(%rbp), %rcx
movl -0x4c(%rbp), %eax
cmpl 0x8(%rcx), %eax
jge 0x60ee0
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movsd (%rcx), %xmm1
subsd -0x48(%rbp), %xmm1
movaps 0x23439(%rip), %xmm0    # 0x840b0
pand %xmm0, %xmm1
movsd 0x2348d(%rip), %xmm0    # 0x84110
mulsd 0xa0(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x60cec
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movsd 0x8(%rcx), %xmm1
subsd -0x40(%rbp), %xmm1
movaps 0x233f0(%rip), %xmm0    # 0x840b0
pand %xmm0, %xmm1
movsd 0x23444(%rip), %xmm0    # 0x84110
mulsd 0xa0(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x60cec
movl -0x4c(%rbp), %ecx
addl $0x1, %ecx
xorl %eax, %eax
subl %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x61242
movq -0xa8(%rbp), %rdi
movsd -0x48(%rbp), %xmm0
movsd %xmm0, -0xc0(%rbp)
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0xb8(%rbp)
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movsd -0xc0(%rbp), %xmm0
movsd -0xb8(%rbp), %xmm1
movsd (%rax), %xmm2
callq 0x613e0
testb $0x1, %al
jne 0x60d3c
jmp 0x60e97
movq -0xa8(%rbp), %rdi
movsd -0x40(%rbp), %xmm0
movsd %xmm0, -0xd0(%rbp)
movsd -0x30(%rbp), %xmm0
movsd %xmm0, -0xc8(%rbp)
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movsd -0xd0(%rbp), %xmm0
movsd -0xc8(%rbp), %xmm1
movsd 0x8(%rax), %xmm2
callq 0x613e0
testb $0x1, %al
jne 0x60d8d
jmp 0x60e97
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movq -0xa8(%rbp), %rdi
movsd (%rax), %xmm0
subsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movsd 0x8(%rcx), %xmm0
subsd -0x30(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movsd -0x48(%rbp), %xmm0
subsd -0x28(%rbp), %xmm0
movsd -0x60(%rbp), %xmm2
movsd -0x40(%rbp), %xmm1
subsd -0x30(%rbp), %xmm1
mulsd -0x58(%rbp), %xmm1
movq %xmm1, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x68(%rbp)
movsd -0x58(%rbp), %xmm1
movaps 0x23286(%rip), %xmm0    # 0x840b0
pand %xmm0, %xmm1
movsd -0x60(%rbp), %xmm0
movaps 0x23276(%rip), %xmm2    # 0x840b0
pand %xmm2, %xmm0
addsd %xmm0, %xmm1
movsd 0x23256(%rip), %xmm0    # 0x840a0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x70(%rbp)
movsd -0x68(%rbp), %xmm1
movaps 0x23251(%rip), %xmm0    # 0x840b0
pand %xmm0, %xmm1
movsd -0x70(%rbp), %xmm0
mulsd 0xa0(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x60e95
cmpq $0x0, -0x20(%rbp)
je 0x60e89
movl -0x4c(%rbp), %ecx
subl $0x1, %ecx
movq -0x20(%rbp), %rax
movl %ecx, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0x61242
jmp 0x60e97
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movq -0xa8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x28(%rbp)
addq $0x10, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x63990
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x30(%rbp)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x60c36
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x63990
movq -0xa8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x28(%rbp)
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x63990
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x30(%rbp)
movl $0x1, -0x74(%rbp)
movq -0xa8(%rbp), %rcx
movl -0x74(%rbp), %eax
cmpl 0x8(%rcx), %eax
jge 0x6123c
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x74(%rbp), %rsi
callq 0x63990
movq -0xa8(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x80(%rbp)
addq $0x10, %rdi
movslq -0x74(%rbp), %rsi
callq 0x63990
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x88(%rbp)
movsd -0x40(%rbp), %xmm1
movsd -0x30(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x60f9a
movsd -0x40(%rbp), %xmm1
movsd -0x88(%rbp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x61217
movsd -0x40(%rbp), %xmm0
ucomisd -0x30(%rbp), %xmm0
jb 0x60fb9
movsd -0x40(%rbp), %xmm0
ucomisd -0x88(%rbp), %xmm0
ja 0x61215
movsd -0x48(%rbp), %xmm0
ucomisd -0x28(%rbp), %xmm0
jbe 0x60fd5
movsd -0x48(%rbp), %xmm0
ucomisd -0x80(%rbp), %xmm0
ja 0x61213
movsd -0x88(%rbp), %xmm0
ucomisd -0x40(%rbp), %xmm0
jne 0x6118b
jp 0x6118b
movq -0xa8(%rbp), %rcx
movl -0x74(%rbp), %eax
movl 0x8(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x61032
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movl -0x74(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x63990
movsd 0x8(%rax), %xmm0
subsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
jmp 0x6105b
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x63990
movsd 0x8(%rax), %xmm0
subsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
movsd -0x90(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x61127
jp 0x61127
movq -0xa8(%rbp), %rcx
movl -0x74(%rbp), %eax
movl 0x8(%rcx), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
jge 0x610ba
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movl -0x74(%rbp), %eax
addl $0x2, %eax
movslq %eax, %rsi
callq 0x63990
movsd 0x8(%rax), %xmm0
subsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
jmp 0x61125
movq -0xa8(%rbp), %rcx
movl -0x74(%rbp), %eax
movl 0x8(%rcx), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
jne 0x610f9
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x63990
movsd 0x8(%rax), %xmm0
subsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
jmp 0x61123
movq -0xa8(%rbp), %rdi
addq $0x10, %rdi
movl $0x1, %esi
callq 0x63990
movsd 0x8(%rax), %xmm0
subsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
jmp 0x61125
jmp 0x61127
movsd 0x22fd9(%rip), %xmm0    # 0x84108
movsd %xmm0, -0x98(%rbp)
movsd -0x88(%rbp), %xmm0
subsd -0x30(%rbp), %xmm0
mulsd -0x90(%rbp), %xmm0
movsd %xmm0, -0x98(%rbp)
movsd -0x98(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x61186
movsd -0x48(%rbp), %xmm1
movsd -0x80(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x61186
cmpl $0x0, -0x34(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x34(%rbp)
jmp 0x61211
movsd -0x88(%rbp), %xmm0
ucomisd -0x30(%rbp), %xmm0
jne 0x6119e
jp 0x6119e
jmp 0x611fe
movsd -0x28(%rbp), %xmm0
movsd -0x40(%rbp), %xmm1
subsd -0x30(%rbp), %xmm1
movsd -0x80(%rbp), %xmm2
subsd -0x28(%rbp), %xmm2
mulsd %xmm2, %xmm1
movsd -0x88(%rbp), %xmm2
subsd -0x30(%rbp), %xmm2
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0xa0(%rbp)
movsd -0x48(%rbp), %xmm1
movsd -0xa0(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x611fc
cmpl $0x0, -0x34(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x34(%rbp)
jmp 0x6120f
cmpl $0x0, -0x34(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x34(%rbp)
jmp 0x61211
jmp 0x61213
jmp 0x61215
jmp 0x61217
movsd -0x80(%rbp), %xmm0
movsd %xmm0, -0x28(%rbp)
movsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x60f22
movl -0x34(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xd0, %rsp
popq %rbp
retq
nop