#!/usr/bin/perl

# punkt_wewnatrz_czworokata( $x, $y, $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3 )
#   Procedura zwraca prawde, jesli punkt ($x,$y) znajduje sie wewnatrz czworokata
#   zdefiniowanego przez punkty p0 ($x0,$y0), p1, p2 oraz p3.
#   Wykorzystywana jest podprocedura punkt_wewnatrz_trojkata().
#

sub punkt_wewnatrz_czworokata {
    my ( $x, $y, $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3 ) = @_;

    return punkt_wewnatrz_trojkata( $x, $y, $x0, $y0, $x1, $y1, $x2, $y2 ) ||
           punkt_wewnatrz_trojkata( $x, $y, $x0, $y0, $x2, $y2, $x3, $y3 )
}

@czworokat = ( 1, 4,  3, 0,  6, 2,  5, 5 );
print "(0, 2): ", punkt_wewnatrz_czworokata( 0, 2,  @czworokat ), "\n";
print "(1, 4): ", punkt_wewnatrz_czworokata( 1, 4,  @czworokat ), "\n";
print "(2, 2): ", punkt_wewnatrz_czworokata( 2, 2,  @czworokat ), "\n";
print "(3, 6): ", punkt_wewnatrz_czworokata( 3, 6,  @czworokat ), "\n";
print "(3, 4): ", punkt_wewnatrz_czworokata( 3, 4,  @czworokat ), "\n";
print "(4, 2): ", punkt_wewnatrz_czworokata( 4, 2,  @czworokat ), "\n";
print "(5, 4): ", punkt_wewnatrz_czworokata( 5, 4,  @czworokat ), "\n";
print "(6, 2): ", punkt_wewnatrz_czworokata( 6, 2,  @czworokat ), "\n";

# punkt_wewnatrz_trojkata( $x, $y, $x0, $y0, $x1, $y1, $x2, $y2 )
# Procedura zwraca prawde, jesli punkt ($x,$y) znajduje sie wewnatrz
# trojkata zdefiniowanego przez punkty ($x0, $y0, $x1, $y1, $x2, $y2).
#

sub punkt_wewnatrz_trojkata {
    my ( $x, $y, $x0, $y0, $x1, $y1, $x2, $y2 ) = @_;

    # Procedura kierunek() pochodzi z wczesniejszej czesci rozdzialu.
    my $cw0 = kierunek( $x0, $y0, $x1, $y1, $x, $y );
    return 1 if abs( $cw0 ) < epsilon; # Pierwsza krawedz.

    my $cw1 = kierunek( $x1, $y1, $x2, $y2, $x, $y );
    return 1 if abs( $cw1 ) < epsilon; # Druga krawedz.

    # Niepowodzenie w przypadku zmiany znaku.
    return 0 if ( $cw0 < 0 and $cw1 > 0 ) or ( $cw0 > 0 and $cw1 < 0 );

    my $cw2 = kierunek( $x2, $y2, $x0, $y0, $x, $y );
    return 1 if abs( $cw2 ) < epsilon; # Trzecia krawedz.

    # Niepowodzenie w przypadku zmiany znaku.
    return 0 if ( $cw0 < 0 and $cw2 > 0 ) or ( $cw0 > 0 and $cw2 < 0 );

    # Sukces!
    return 1;
}

# kierunek( $x0, $y0, $x1, $y1, $x2, $y2 )
#    Procedura zwraca wartosc dodatnia, jesli przesuwajac sie z p0 (x0, y0) 
#    do przez p1 do p2 nalezy skrecic w prawo, wartosc ujemna, jesli nalezy
#    skrecic w lewo.
#    Zero jest zwracane w przypadku, gdy wszystkie trzy punkty leza na tej samej
#    linii prostej. Nalezy jednak uwazac na bledy zmiennoprzecinkowe.
#
sub kierunek {
    my ( $x0, $y0, $x1, $y1, $x2, $y2 ) = @_;
    return ( $x2 - $x0 ) * ( $y1 - $y0 ) - ( $x1 - $x0 ) * ( $y2 - $y0 );
}


