Reputation: 512
The problem input is specified by three points A, B, C
, each with two coordinates x, y
.
The solution should be an array of all points inside the the triangle with natural coordinates.
The input is:
A, B, C
The output is: all named point on the figure
Please note that I'm trying to calculate all the points not count them so this question differs from mine quite a bit.
What I'm having trouble with:
Mainly the problem is that, specifying all three segments would require to calculate the coefficients a, b
for all segments which could extend my code quite a bit because I would have to cover all the cases of horizontal and vertical lines.
Then the best method I could come up with would be:
x'es
from min x
of points A, B, C
to the max.y's
from min y
of points A, B, C
to the max.numpy
. The high number of inequalities is the second hardest problem.Generally any way I can think of doing this would require me to write a lot of code with a lot of possible bugs. Also the more instructions I write, the lower the performance gets because of many non-trivial computational methods used.
Any help with a simpler solution would be much appreciated.
Upvotes: 4
Views: 4792
Reputation: 398
You can find the line through each pair of points (lines AB, BC, AC) and check for these lines which side is the inside of the triangle. The points that lie on the 'inside'-side of all lines are inside the triangle:
def insidetriangle((x1,x2,x3),(y1,y2,y3)):
import numpy as np
xs=np.array((x1,x2,x3),dtype=float)
ys=np.array((y1,y2,y3),dtype=float)
# The possible range of coordinates that can be returned
x_range=np.arange(np.min(xs),np.max(xs)+1)
y_range=np.arange(np.min(ys),np.max(ys)+1)
# Set the grid of coordinates on which the triangle lies. The centre of the
# triangle serves as a criterion for what is inside or outside the triangle.
X,Y=np.meshgrid( x_range,y_range )
xc=np.mean(xs)
yc=np.mean(ys)
# From the array 'triangle', points that lie outside the triangle will be
# set to 'False'.
triangle = np.ones(X.shape,dtype=bool)
for i in range(3):
ii=(i+1)%3
if xs[i]==xs[ii]:
include = X *(xc-xs[i])/abs(xc-xs[i]) > xs[i] *(xc-xs[i])/abs(xc-xs[i])
else:
poly=np.poly1d([(ys[ii]-ys[i])/(xs[ii]-xs[i]),ys[i]-xs[i]*(ys[ii]-ys[i])/(xs[ii]-xs[i])])
include = Y *(yc-poly(xc))/abs(yc-poly(xc)) > poly(X) *(yc-poly(xc))/abs(yc-poly(xc))
triangle*=include
# Output: 2 arrays with the x- and y- coordinates of the points inside the
# triangle.
return X[triangle],Y[triangle]
3 inequalities are solved in the loop, resulting in boolean arrays that are multiplied to yield only the points inside the triangle.
Edit: The loop can be written a little more self-explanatory as:
for i in range(3):
ii=(i+1)%3
if xs[i]==xs[ii]:
if xc>xs:
include = (X > xs[i])
else:
include = (X < xs[i])
else:
slope=(ys[ii]-ys[i])/(xs[ii]-xs[i])
poly=np.poly1d([slope,ys[i]-xs[i]*slope])
if yc>poly(xc):
include = (Y > poly(X))
else:
include = (Y < poly(X))
triangle*=include
Upvotes: 4
Reputation: 80187
You definitely need triangle rasterization.
Arbitrary article. You would correct starting and ending points of every scanline to ensure they are inside the triangle.
Upvotes: 2