Peter’s solutions: week 101 — 22 February 2021

THE WEEKLY CHALLENGE
Spiral triangle

The Perl Camel

Task 2

Origin-containing triangle

You are given three points in the plane, as a list of six co-ordinates: A=(x1,y1), B=(x2,y2) and C=(x3,y3).

Write a script to find out if the triangle formed by the given three co-ordinates contains the origin (0,0).

Print 1 if found, otherwise 0.

Examples


Example 1
Input: A=(0,1), B=(1,0) and C=(2,2)
Output: 0 because that triangle does not contain (0,0).

Example 2
Input: A=(1,1), B=(-1,1) and C=(0,-3)
Output: 1 because that triangle contains (0, 0) in 
its interior.

Example 3
Input: A=(0,1), B=(2,0) and C=(-6,0)
Output: 1 because (0,0) is on the edge connecting B and C.

Analysis

This is a well-known mathematical problem, for which there are a number of established solutions. The one that appeals to me most uses barycentric coordinates.

In the current context, the 3 barycentric coordinates of the point at the cartesian origin are the signed proportions of lines from each vertex of the triangle which pass through the origin and end when they meet the opposite side of the triangle.

If the point is within the triangle, the barycentric coordinates will thus all be in the range 0 to +1.

If any of them is exactly 1 then the point lies on one of the triangle's edges, and if any is 0, the point is at a vertex. I have chosen to regard these as lying within the triangle - ie returned a 1 response.

Like almost every method, the answer for points very close to or on the triangle's sides depends on floating point arithmetic, so may be marginally inaccurate. However, this is arguably less likely than in a solution based on cartesian coordinates, where lines with infinite or near infinite gradient (eg x = 0) require treatment as exceptions.

Try it 

Try running the script with any input:



example: (1, 1), {-1, 1), (0, -3)

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2021-02-22
use utf8;     # Week 101 - task 2 - Origin-containing triangle
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

origin_in_triangle(0, 1, 1, 0, 2, 2);
origin_in_triangle(1, 1, -1, 1, 0, -3);
origin_in_triangle(0, 1, 2, 0, -6, 0);

sub origin_in_triangle {
    
    my ($x1, $y1, $x2, $y2, $x3, $y3, $a, $b, $c);
    
    # initialise
    ($x1, $y1, $x2, $y2, $x3, $y3) = @_;
    
    # calculate barycentric coordinates
    $a = (($y2 - $y3) * (0   - $x3) + ($x3 - $x2) * (0   - $y3)) / 
         (($y2 - $y3) * ($x1 - $x3) + ($x3 - $x2) * ($y1 - $y3));
    $b = (($y3 - $y1) * (0   - $x3) + ($x1 - $x3) * (0   - $y3)) / 
         (($y2 - $y3) * ($x1 - $x3) + ($x3 - $x2) * ($y1 - $y3));
    $c = 1 - $a - $b;
    
    # report
    say qq[\nInput:  ($x1, $y1), ($x2, $y2), ($x3, $y3)];
    say qq[Output: ] . ((0 <= $a && $a <= 1 && 0 <= $b && $b <= 1 && 0 <= $c && $c <= 1) ? 1 : 0);
}   

10 lines of code
Completed after the closing date and not submitted to GitHub

Output


Input:  (0, 1), (1, 0), (2, 2)
Output: 0

Input:  (1, 1), (-1, 1), (0, -3)
Output: 1

Input:  (0, 1), (2, 0), (-6, 0)
Output: 1

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain