// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdx, %rbx
movq %rdi, %r14
testq %rdx, %rdx
je 0x22e5f
orl $-0x1, (%rbx)
movsd 0x58(%r14), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0xa0(%r14), %xmm0
movapd %xmm0, 0x40(%rsp)
movupd (%rsi), %xmm1
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
movapd %xmm0, 0x10(%rsp)
divpd %xmm0, %xmm1
movapd %xmm1, 0x20(%rsp)
movapd %xmm1, %xmm0
callq 0x81a0
movapd %xmm0, 0x30(%rsp)
movapd 0x20(%rsp), %xmm0
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
callq 0x81a0
movapd 0x30(%rsp), %xmm6
unpcklpd %xmm0, %xmm6            # xmm6 = xmm6[0],xmm0[0]
mulpd 0x10(%rsp), %xmm6
movapd 0x40(%rsp), %xmm0
divsd 0x131aa(%rip), %xmm0    # 0x36078
movsd 0x8(%rsp), %xmm1
subsd %xmm0, %xmm1
xorl %eax, %eax
ucomisd %xmm6, %xmm1
ja 0x23237
movsd 0x60(%r14), %xmm1
subsd %xmm0, %xmm1
movapd %xmm6, %xmm7
unpckhpd %xmm6, %xmm7            # xmm7 = xmm7[1],xmm6[1]
ucomisd %xmm7, %xmm1
ja 0x23237
movsd 0x68(%r14), %xmm1
addsd %xmm0, %xmm1
ucomisd %xmm1, %xmm6
ja 0x23237
addsd 0x70(%r14), %xmm0
ucomisd %xmm0, %xmm7
ja 0x23237
movq 0x10(%r14), %r15
movupd (%r15), %xmm8
movapd %xmm8, %xmm0
subpd %xmm6, %xmm0
andpd 0x130f2(%rip), %xmm0    # 0x36030
pshufd $0xee, %xmm0, %xmm1     # xmm1 = xmm0[2,3,2,3]
addsd %xmm0, %xmm1
movapd 0x40(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x22f5b
pushq $-0x1
popq %rax
jmp 0x23237
movslq 0x8(%r14), %r14
movsd 0x13119(%rip), %xmm4    # 0x36080
mulsd %xmm0, %xmm4
movapd %xmm8, %xmm0
unpckhpd %xmm8, %xmm0            # xmm0 = xmm0[1],xmm8[1]
leaq 0x18(%r15), %r13
xorl %r12d, %r12d
movapd 0x130ac(%rip), %xmm3    # 0x36030
movapd %xmm0, 0x70(%rsp)
movsd %xmm0, 0x10(%rsp)
movapd %xmm8, %xmm1
movapd %xmm6, 0x30(%rsp)
movapd %xmm7, 0x20(%rsp)
movapd %xmm8, 0x80(%rsp)
movsd %xmm4, 0x60(%rsp)
leaq 0x1(%r12), %rbp
cmpq %r14, %rbp
jge 0x230db
movsd -0x8(%r13), %xmm2
movapd %xmm2, %xmm0
subsd %xmm6, %xmm0
andpd %xmm3, %xmm0
ucomisd %xmm0, %xmm4
jbe 0x22fef
movsd (%r13), %xmm0
subsd %xmm7, %xmm0
andpd %xmm3, %xmm0
ucomisd %xmm0, %xmm4
ja 0x23225
movapd %xmm6, %xmm0
movsd %xmm1, 0x68(%rsp)
movsd %xmm2, 0x8(%rsp)
callq 0x232cd
movapd 0x20(%rsp), %xmm7
movsd (%r13), %xmm2
testb %al, %al
je 0x230a5
movapd %xmm7, %xmm0
movsd 0x10(%rsp), %xmm1
movsd %xmm2, 0x58(%rsp)
callq 0x232cd
movsd 0x58(%rsp), %xmm2
movapd 0x20(%rsp), %xmm7
testb %al, %al
je 0x230a5
movsd 0x8(%rsp), %xmm0
movsd 0x68(%rsp), %xmm3
subsd %xmm3, %xmm0
movapd %xmm2, %xmm1
movsd 0x10(%rsp), %xmm4
subsd %xmm4, %xmm1
movapd 0x30(%rsp), %xmm5
subsd %xmm3, %xmm5
movapd %xmm7, %xmm3
subsd %xmm4, %xmm3
mulsd %xmm0, %xmm3
mulsd %xmm1, %xmm5
subsd %xmm3, %xmm5
movapd 0x12faf(%rip), %xmm3    # 0x36030
andpd %xmm3, %xmm0
andpd %xmm3, %xmm1
addsd %xmm0, %xmm1
addsd %xmm1, %xmm1
andpd %xmm3, %xmm5
mulsd 0x40(%rsp), %xmm1
ucomisd %xmm5, %xmm1
ja 0x2322d
addq $0x10, %r13
movq %rbp, %r12
movsd %xmm2, 0x10(%rsp)
movsd 0x8(%rsp), %xmm1
movapd 0x30(%rsp), %xmm6
movapd 0x80(%rsp), %xmm8
movsd 0x60(%rsp), %xmm4
movapd 0x12f5a(%rip), %xmm3    # 0x36030
jmp 0x22fb1
leal -0x1(%r14), %eax
leal -0x2(%r14), %ecx
movslq %ecx, %rdx
movslq %eax, %rsi
leaq 0x20(%r15), %rdi
xorl %eax, %eax
pushq $0x1
popq %r8
xorpd %xmm0, %xmm0
movapd 0x70(%rsp), %xmm1
cmpq %r14, %r8
jge 0x23237
movapd %xmm8, %xmm3
movapd %xmm1, %xmm2
movsd -0x10(%rdi), %xmm8
movsd -0x8(%rdi), %xmm1
ucomisd %xmm7, %xmm2
jb 0x2312a
ucomisd %xmm7, %xmm1
ja 0x23219
ucomisd %xmm2, %xmm7
jb 0x2313a
ucomisd %xmm1, %xmm7
ja 0x23219
ucomisd %xmm3, %xmm6
jbe 0x2314b
ucomisd %xmm8, %xmm6
ja 0x23219
ucomisd %xmm7, %xmm1
jne 0x2317b
jp 0x2317b
cmpq %rsi, %r8
movq %r15, %r9
cmovlq %rdi, %r9
movsd 0x8(%r9), %xmm3
subsd %xmm1, %xmm3
ucomisd %xmm0, %xmm3
jne 0x231e0
jp 0x231e0
cmpq %rdx, %r8
jge 0x231bb
movsd 0x18(%rdi), %xmm3
jmp 0x231dc
ucomisd %xmm2, %xmm1
jne 0x23183
jnp 0x231c8
movapd %xmm7, %xmm4
subsd %xmm2, %xmm4
movapd %xmm8, %xmm5
subsd %xmm3, %xmm5
mulsd %xmm4, %xmm5
movapd %xmm1, %xmm4
subsd %xmm2, %xmm4
divsd %xmm4, %xmm5
addsd %xmm3, %xmm5
xorl %r9d, %r9d
testl %eax, %eax
sete %r9b
ucomisd %xmm6, %xmm5
cmovael %r9d, %eax
jmp 0x23219
cmpq %r8, %rcx
jne 0x231d6
movapd 0x70(%rsp), %xmm3
jmp 0x231dc
xorl %r9d, %r9d
testl %eax, %eax
sete %r9b
movl %r9d, %eax
jmp 0x23219
movsd 0x18(%r15), %xmm3
subsd %xmm1, %xmm3
movapd %xmm1, %xmm4
subsd %xmm2, %xmm4
mulsd %xmm3, %xmm4
movapd %xmm6, %xmm2
cmpnlepd %xmm8, %xmm2
xorpd %xmm3, %xmm3
cmpnltpd %xmm4, %xmm3
orpd %xmm2, %xmm3
movd %xmm3, %r9d
xorl %r10d, %r10d
testl %eax, %eax
sete %r10b
testb $0x1, %r9b
cmovel %r10d, %eax
incq %r8
addq $0x10, %rdi
jmp 0x230fd
pushq $-0x2
popq %rax
subl %r12d, %eax
jmp 0x23237
xorl %eax, %eax
testq %rbx, %rbx
je 0x23237
movl %r12d, (%rbx)
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop