In the code below I have calculated which triangles cover a certain point. Now I am trying to let the function perimeter
calculate the perimeter of the left over triangles which can be found in triangle_fit
. And when I know the perimeters of these triangles I want to chose the smallest triangle. I did some attempts but the function will only recognize x1
, y1
, x2
, ...
.
import itertools
import math
def area(x1, y1, x2, y2, x3, y3):
return abs((x1 * (y2 - y3) x2 * (y3 - y1)
x3 * (y1 - y2)) / 2.0)
def isInside(x1, y1, x2, y2, x3, y3, x, y):
A = area (x1, y1, x2, y2, x3, y3)
A1 = area (x, y, x2, y2, x3, y3)
A2 = area (x1, y1, x, y, x3, y3)
A3 = area (x1, y1, x2, y2, x, y)
if(A == A1 A2 A3):
return True
else:
return False
def perimeter (x1, y1, x2, y2, x3, y3):
return abs(math.sqrt((x1-x2)**2 (y1-y2)**2) math.sqrt((x2-x3)^2
(y2-y3)**2) math.sqrt((x3-x1)**2 (y3-y1)**2))
points = [(0,10), (0,0), (10,0), (10,10), (5,2), (2,2)]
P = (5,1)
triangle_fit = []
for triangle in itertools.combinations(points, 3):
p1, p2, p3 = triangle
if isInside(*p1, *p2, *p3, *P):
triangle_fit.append(triangle)
print(triangle_fit)
CodePudding user response:
You can do it by sorting the list of triangles by their perimeter which will move the smaller ones to the beginning (note there can be more than one that is smallest if they have the same perimeter).
To make doing this easier I changed the calling sequence of your perimeter()
function to accept a sequence of three points to match the format of the contents of the triangle_fit
list. I also changed it to use the math.hypot()
function to compute the Euclidean-distance between each pair points. Doing this not only makes it a little faster, it also fixed a bug in your code I noticed where you used ^
instead of **
for exponentiation.
import itertools
import math
def area(x1, y1, x2, y2, x3, y3):
return abs((x1 * (y2 - y3)
x2 * (y3 - y1)
x3 * (y1 - y2)) / 2.0)
def is_inside(x1, y1, x2, y2, x3, y3, x, y):
A = area(x1, y1, x2, y2, x3, y3)
A1 = area(x, y, x2, y2, x3, y3)
A2 = area(x1, y1, x, y, x3, y3)
A3 = area(x1, y1, x2, y2, x, y)
return A == A1 A2 A3
def perimeter(points):
(x1, y1), (x2, y2), (x3, y3) = points
return (math.hypot(x1-x2, y1-y2)
math.hypot(x2-x3, y2-y3)
math.hypot(x3-x1, y3-y1))
points = [(0,10), (0,0), (10,0), (10,10), (5,2), (2,2)]
P = (5,1)
triangle_fit = []
for triangle in itertools.combinations(points, 3):
p1, p2, p3 = triangle
if is_inside(*p1, *p2, *p3, *P):
triangle_fit.append(triangle)
triangle_fit.sort(key=perimeter) # Sort by perimeter.
for points in triangle_fit:
print(f'{points}: area={area(*points[0], *points[1], *points[2]):.2f}')