SRL Archive - OSR Help

random point in triangle help.


g0tp0t

2010-10-27 13:38:47

im trying to make a function the returns a random point in a triangle.

what i have the script dong is taking a random y value-between the lowest and highest y values- then trying to find the minimum and maximum possible x values for that y.

i need to find the two points i circled in red

g0tp0t

2010-10-27 16:08:37

anyone know how to help? deleteing this post

i luffs yeww

2010-10-27 17:02:48

Make a rectangle by making a triangle on either side of the legs (hypotenuse of both new triangles on a leg of the original triangle) and search for the points in the rectangle and then exclude any points in the new triangles.

Or use inequalities. I think you could make that work.

g0tp0t

2010-10-27 17:07:01

but how do i find whether the points are in the triangles.

EDIT: your idea is good, better than mine. i think it would use less code if instead of testing those 3 extra triangles, i just tested whether the point is in the main triangle.

Edit2: inequalities is good. ill use that. ill post my finished point sorting code in a min.

g0tp0t

2010-10-27 17:18:19

function RandomPointInTriangle(p1,p2,p3:tpoint):tpoint;
var x1,x2,x3,y1,y2,y3:integer;
begin
//sort points from top left to bottom right.
//First find topleftmost point
if min(p1.x,min(p2.x,p3.x)) = p1.x then
begin
if p1.x = p2.x then
begin
if min(p1.y,p2.y) = p1.y then
begin
x1 := p1.x;
y1 := p1.y;
end else
begin
x1 := p2.x;
y1 := p2.y;
end;
end else if p1.x = p3.x then
begin
if min(p1.y,p3.y) = p1.y then
begin
x1 := p1.x;
y1 := p1.y;
end else
begin
x1 := p3.x;
y1 := p3.y;
end;
end;
//now find bottomrightmost point
if p1.x = p2.x then
begin
if max(p1.y,p2.y) = p1.y then
begin
x3 := p1.x;
y3 := p1.y;
end else
begin
x3 := p2.x;
y3 := p2.y;
end;
end else if p1.x = p3.x then
begin
if max(p1.y,p3.y) = p1.y then
begin
x3 := p1.x;
y3 := p1.y;
end else
begin
x3 := p3.x;
y3 := p3.y;
end;
end;
//now find the point we havnt used yet
if x1 = p1.x and y1 = p1.y then
begin
if x3 = p2.x and y3 = p2.y then
begin
x2 := p3.x;
y2 := p3.y;
end;

if x3 = p3.x and y3 = p3.y then
begin
x2 := p2.x;
y2 := p2.y;
end;
end;

if x1 = p2.x and y1 = p2.y then
begin
if x3 = p1.x and y3 = p1.y then
begin
x2 := p3.x;
y2 := p3.y;
end;

if x3 = p3.x and y3 = p3.y then
begin
x2 := p1.x;
y2 := p1.y;
end;
end;

if x1 = p3.x and y1 = p3.y then
begin
if x3 = p1.x and y3 = p1.y then
begin
x2 := p2.x;
y2 := p2.y;
end;

if x3 = p2.x and y3 = p2.y then
begin
x2 := p1.x;
y2 := p1.y;
end;
end;
end;
writeln(x1)
writeln(y1)
writeln(x2)
writeln(y2)
writeln(x3)
writeln(y3)
{
//set x and y values
x1 := p1.x;
y1 := p1.y;
x2 := p2.x;
y2 := p2.y;
x3 := p3.x;
y3 := p3.y;
}
end;

result:

[Error] (57:32): Type mismatch at line 56
Compiling failed.

i luffs yeww

2010-10-27 18:03:01

What's line 56?

g0tp0t

2010-10-27 18:11:45

if x1 = p1.x and y1 = p1.y then

i luffs yeww

2010-10-27 18:46:22

Change x1-3 and y1-3 to Extended maybe?

g0tp0t

2010-10-27 18:56:38

i cant because it is a coordinate.

Feroc1ty

2010-10-27 19:00:52

What do you need to do for it to compile, do you need to convert a variable to another type or something?

g0tp0t

2010-10-27 19:05:47

thats what im trying to fugre out

when i added the peice that gets the not min and not max coordinate. the last peice.

EDIT: i got it. when i used and, it was conecting the integer instead of the equations. i added parenthesis and now it works =D

TomTuff

2010-10-27 19:06:19

From: g0tp0t
i cant because it is a coordinate.


deal with extendeds until you have the point, then at the end of the function, do ceil() or floor(), then use whatever function turns a float to an integer

g0tp0t

2010-10-27 19:16:44

now that it works, it doesnt work perfectly. somewhere this code is missing a possible scenario. if i do this:
function RandomPointInTriangle(p1,p2,p3:tpoint):tpoint;
var x1,x2,x3,y1,y2,y3:integer;
begin
//sort points from top left to bottom right.
//First find topleftmost point
if min(p1.x,min(p2.x,p3.x)) = p1.x then
begin
if p1.x = p2.x then
begin
if min(p1.y,p2.y) = p1.y then
begin
x1 := p1.x;
y1 := p1.y;
end else
begin
x1 := p2.x;
y1 := p2.y;
end;
end else if p1.x = p3.x then
begin
if min(p1.y,p3.y) = p1.y then
begin
x1 := p1.x;
y1 := p1.y;
end else
begin
x1 := p3.x;
y1 := p3.y;
end;
end;
//now find bottomrightmost point
if p1.x = p2.x then
begin
if max(p1.y,p2.y) = p1.y then
begin
x3 := p1.x;
y3 := p1.y;
end else
begin
x3 := p2.x;
y3 := p2.y;
end;
end else if p1.x = p3.x then
begin
if max(p1.y,p3.y) = p1.y then
begin
x3 := p1.x;
y3 := p1.y;
end else
begin
x3 := p3.x;
y3 := p3.y;
end;
end;
//now find the point we havnt used yet
if (x1 = p1.x) and (y1 = p1.y) then
begin
if (x3 = p2.x) and (y3 = p2.y )then
begin
x2 := p3.x;
y2 := p3.y;
end;

if (x3 = p3.x) and (y3 = p3.y) then
begin
if (x1 = p1.x) and (y1 = p1.y) then
begin
x2 := p2.x;
y2 := p2.y;
end;
end;
end;

if (x1 = p2.x) and (y1 = p2.y) then
begin
if (x3 = p1.x) and (y3 = p1.y) then
begin
x2 := p3.x;
y2 := p3.y;
end;

if (x3 = p3.x) and (y3 = p3.y) then
begin
x2 := p1.x;
y2 := p1.y;
end;
end;

if (x1 = p3.x) and (y1 = p3.y) then
begin
if (x3 = p1.x) and (y3 = p1.y) then
begin
x2 := p2.x;
y2 := p2.y;
end;

if (x3 = p2.x) and (y3 = p2.y) then
begin
x2 := p1.x;
y2 := p1.y;
end;
end; {}
end;
writeln(x1)
writeln(y1)
writeln(x2)
writeln(y2)
writeln(x3)
writeln(y3)
{
//set x and y values
x1 := p1.x;
y1 := p1.y;
x2 := p2.x;
y2 := p2.y;
x3 := p3.x;
y3 := p3.y;
}
end;
begin
RandomPointInTriangle(point(2,2),point(1,1),point(1,3));
end.
, then it prints out all the values as 0

i luffs yeww

2010-10-27 19:21:39

MOAR DEBUGGING. a

g0tp0t

2010-10-27 19:38:37

ok, i think i figured it out. =\

i dont have any scenarios for when the first point isnt put in first. lol

g0tp0t

2010-10-27 19:46:18

ok, this way is realy complicated. anyone know of an easier way to sort the points

Feroc1ty

2010-10-27 19:54:26

You ask very vague shit, which will make everyone look through your horrible code to even understand what you're asking, and at that point they've invested so much time into looking through the script they'll realize that it's a waste even trying to help.

How about you ask general questions which don't relate to your code, so we can help you with the general concept which you can code yourself.

g0tp0t

2010-10-27 21:23:04

im getting an out of range error, i dont know what it means though

function OrganiseTriPoints(p1,p2,p3:tpoint):TPointArray;
var x1,x2,x3,y1,y2,y3,pt1,pt2,pt3,yrange:integer;
begin
yrange := max(p1.y,max(p2.y,p3.y))-min(p1.y,min(p2.y,p3.y));
pt1 := p1.x*yrange+p1.y;
pt2 := p2.x*yrange+p2.y;
pt3 := p3.x*yrange+p3.y;
//check for the upperleftmost point
if min(pt1,min(pt2,pt3)) = pt1 then
begin
x1 := p1.x;
y1 := p1.y;
end;

if min(pt1,min(pt2,pt3)) = pt2 then
begin
x1 := p2.x;
y1 := p2.y;
end;

if min(pt1,min(pt2,pt3)) = pt3 then
begin
x1 := p3.x;
y1 := p3.y;
end;
//check for the bottomrightmost point
if max(pt1,max(pt2,pt3)) = pt1 then
begin
x3 := p1.x;
y3 := p1.y;
end;

if max(pt1,max(pt2,pt3)) = pt2 then
begin
x3 := p2.x;
y3 := p2.y;
end;

if max(pt1,max(pt2,pt3)) = pt3 then
begin
x3 := p3.x;
y3 := p3.y;
end;
//find the middlemost point
if ((pt1 < pt2) and (pt1 > pt3)) or ((pt1 > pt2) and (pt1 < pt3)) then
begin
x2 := p2.x;
y2 := p2.y;
end;

if ((pt2 < pt1) and (pt2 > pt3)) or ((pt2 > pt1) and (pt2 < pt3)) then
begin
x2 := p2.x;
y2 := p2.y;
end;

if ((pt3 < pt2) and (pt3 > pt1)) or ((pt3 > pt2) and (pt3 < pt1)) then
begin
x2 := p3.x;
y2 := p3.y;
end;
result := [point(x1,y1),point(x2,y2),point(x3,y3)]
end;

function getslope(p1,p2:tpoint; intercept : double):extended;
begin
result := ( p2.y-p1.y)/(p2.x-p1.x);
intercept := result * p1.x-p1.y;
end;

function IsInTri(p,p1,p2,p3:TPoint):boolean;
var tpa : TPointArray; c1,c2,c3:TPoint; slope1,slope2,int1,int2:extended;
begin
result := false;
tpa := OrganiseTriPoints(p1,p2,p3);
c1 := tpa[1];
c2 := tpa[2];
c3 := tpa[3];
slope1 := getslope(c1,c2,int1);
slope2 := getslope(c2,c3,int2);
if (p.y > (slope1 * p.x+int1)) then
if (p.y < (slope2 * p.x+int2)) then
result := true;
end;

begin
IsInTri(point(2,2),point(1,1),point(5,5),point(5,1))
end.

error:

Compiled succesfully in 47 ms.
Error: Out Of Range at line 79

g0tp0t

2010-10-27 21:34:06

something is wrong with my getslop function because when i had it print out the values of slope1 slope2 int1 and int 2, i got 1,0,0,and 0 respectively

i luffs yeww

2010-10-27 21:35:19


c1 := tpa[1];
c2 := tpa[2];
c3 := tpa[3];

should be


c1 := tpa[0];
c2 := tpa[1];
c3 := tpa[2];

I believe.


intercept := result * (p1.x-p1.y);

should be


intercept := result * (p1.x-p1.y);

g0tp0t

2010-10-27 21:36:39

ty
lol, yup. i shoudl have mentioned that i got that. lol

my new problem is my getslope function. it is supposed to return the slope and y intercept but i get values way off

i luffs yeww

2010-10-27 21:38:26

I showed the fix. You forgot that scripts will be ran as scripted. It will do the order of operations correctly even if you know it should be different.

g0tp0t

2010-10-28 09:23:18

i took a whole new aproach and its very simple. it isnt working though.

var
points:TPointArray;
np:TPoint;
function OrganiseTriPoints(p1,p2,p3:tpoint):TPointArray;
var x1,x2,x3,y1,y2,y3,pt1,pt2,pt3,yrange:integer;
begin
yrange := max(p1.y,max(p2.y,p3.y))-min(p1.y,min(p2.y,p3.y));
pt1 := p1.x*yrange+p1.y;
pt2 := p2.x*yrange+p2.y;
pt3 := p3.x*yrange+p3.y;
//check for the upperleftmost point
if min(pt1,min(pt2,pt3)) = pt1 then
begin
x1 := p1.x;
y1 := p1.y;
end;

if min(pt1,min(pt2,pt3)) = pt2 then
begin
x1 := p2.x;
y1 := p2.y;
end;

if min(pt1,min(pt2,pt3)) = pt3 then
begin
x1 := p3.x;
y1 := p3.y;
end;
//check for the bottomrightmost point
if max(pt1,max(pt2,pt3)) = pt1 then
begin
x3 := p1.x;
y3 := p1.y;
end;

if max(pt1,max(pt2,pt3)) = pt2 then
begin
x3 := p2.x;
y3 := p2.y;
end;

if max(pt1,max(pt2,pt3)) = pt3 then
begin
x3 := p3.x;
y3 := p3.y;
end;
//find the middlemost point
if ((pt1 < pt2) and (pt1 > pt3)) or ((pt1 > pt2) and (pt1 < pt3)) then
begin
x2 := p2.x;
y2 := p2.y;
end;

if ((pt2 < pt1) and (pt2 > pt3)) or ((pt2 > pt1) and (pt2 < pt3)) then
begin
x2 := p2.x;
y2 := p2.y;
end;

if ((pt3 < pt2) and (pt3 > pt1)) or ((pt3 > pt2) and (pt3 < pt1)) then
begin
x2 := p3.x;
y2 := p3.y;
end;
result := [point(x1,y1),point(x2,y2),point(x3,y3)]
end;


function areatri(p1,p2,p3:TPoint):extended; //gets the area of a triangle
var tpa:TPointArray;w,h:extended;
begin
tpa := OrganiseTriPoints(p1,p2,p3);
w := tpa[2].x-tpa[0].x;
h := max(tpa[0].y,max(tpa[1].y,tpa[2].y))-min(tpa[0].y,min(tpa[1].y,tpa[2].y));
result := w*h*0.5
end;

function IsInTri(p,p1,p2,p3:TPoint):boolean;
var sum:extended;
begin //This will split the triangle into 3 smaller ones and get the total area.
//If the area is more than the base triangle then point is outside.
sum := areatri(p,p1,p2)+areatri(p,p2,p3)+areatri(p,p3,p1);
result := (abs(sum - areatri(p1,p2,p3))<1);
end;
//main
begin
points := [point(0,767),point(512,0),point(1023,767)]
points := OrganiseTriPoints(points[0],points[1],points[2]);
np := point(RandomRange(points[0].x,points[2].x),RandomRange(max(points[0].y,max(points[1].y,points[2].y))-min(points[0].y,min(points[1].y,points[2].y)),min(points[0].y,min(points[1].y,points[2].y))));
writeln(np);
writeln(IsInTri(np,points[0],points[1],points[2]));
end.

is that considered clean? i don't know how to use case statements in simba yet so dont count that.

i luffs yeww

2010-10-28 18:19:01


case Random(3) of
0: Writeln('Bob says hi.');
1: Writeln('Margret says bye.');
2..5: Writeln('See Spot run.');
6, 9, 10: Writeln('Run, Spot, run.');
7, 8: begin
Writeln('Spot is tired.');
Writeln('Spot is sleeping.');
end;
end;

g0tp0t

2010-10-29 08:00:03

oh. thanks. do you or anyone else know what internal error 20 means? i haven't found anything wrong in the script.

EDIT: here is with the cases:
var
points:TPointArray;
np:TPoint;
function OrganiseTriPoints(p1,p2,p3:tpoint):TPointArray;
var x1,x2,x3,y1,y2,y3,pt1,pt2,pt3,yrange:integer;
begin
yrange := max(p1.y,max(p2.y,p3.y))-min(p1.y,min(p2.y,p3.y));
pt1 := p1.x*yrange+p1.y;
pt2 := p2.x*yrange+p2.y;
pt3 := p3.x*yrange+p3.y;
//check for the upperleftmost point

case min(pt1,min(pt2,pt3)) of
pt1:
begin
x1 := p1.x;
y1 := p1.y;
end;
pt2:
begin
x1 := p2.x;
y1 := p2.y;
end;
pt3:
begin
x1 := p3.x;
y1 := p3.y;
end;
end;
//check for the bottomrightmost point
case max(pt1,max(pt2,pt3)) of
pt1:
begin
x3 := p1.x;
y3 := p1.y;
end;
pt2:
begin
x3 := p2.x;
y3 := p2.y;
end;
pt3:
begin
x3 := p3.x;
y3 := p3.y;
end;
end;
//find the middlemost point
if ((pt1 < pt2) and (pt1 > pt3)) or ((pt1 > pt2) and (pt1 < pt3)) then
begin
x2 := p2.x;
y2 := p2.y;
end;

if ((pt2 < pt1) and (pt2 > pt3)) or ((pt2 > pt1) and (pt2 < pt3)) then
begin
x2 := p2.x;
y2 := p2.y;
end;

if ((pt3 < pt2) and (pt3 > pt1)) or ((pt3 > pt2) and (pt3 < pt1)) then
begin
x2 := p3.x;
y2 := p3.y;
end;
result := [point(x1,y1),point(x2,y2),point(x3,y3)]
end;


function areatri(p1,p2,p3:TPoint):extended; //gets the area of a triangle
var tpa:TPointArray;w,h:extended; //gets the difference between leftmost and rightmost points
begin //then it gets difference of min and max height.
tpa := OrganiseTriPoints(p1,p2,p3); //multiplies width and heith then divides that in half for area
w := tpa[2].x-tpa[0].x;
h := max(tpa[0].y,max(tpa[1].y,tpa[2].y))-min(tpa[0].y,min(tpa[1].y,tpa[2].y));
result := w*h*0.5
end;

function IsInTri(p,p1,p2,p3:TPoint):boolean;
var sum:extended;
begin //This will split the triangle into 3 smaller ones and sum the area of all three.
//If the area is more than the base triangle then point is outside.
sum := areatri(p,p1,p2)+areatri(p,p2,p3)+areatri(p,p3,p1);
result := (abs(sum - areatri(p1,p2,p3))<1);
end;
//main
begin
points := [point(0,767),point(512,0),point(1023,767)]
points := OrganiseTriPoints(points[0],points[1],points[2]);
np := point(RandomRange(points[0].x,points[2].x),RandomRange(max(points[0].y,max(points[1].y,points[2].y))-min(points[0].y,min(points[1].y,points[2].y)),min(points[0].y,min(points[1].y,points[2].y))));
writeln(np);
writeln(IsInTri(np,points[0],points[1],points[2]));
end.

Camaro'

2010-11-19 16:58:12

This thread is a little old, but heck. If you still need it, I think all you would have to do is generate aa and bb.



function RandomPointInTriangle (A, B,C :TPoint): TPoint
var
aa, bb. cc: extended;
rndX, rndY : integer;

begin
aa:= random number between 0.0 and 1.0 ; //after these two variables are figured out, it should work :)
bb := random # between 0.0 and 1.0;
if (aa + bb > 1.0) then
begin
a := 1 - a;
b := 1 - b;
end;

c := 1 - a - b;

rndX := Round((aa*A.x)+(bb*B.x)+(cc*C.x));
rndY := Round ((a*A.y)+(b*B.y)+(c*C.y));

Result := Point(rndX, rndY);
end;


Bad Boy JH

2010-11-22 08:45:59

if people are still posting…get a load of this….

RandomPointInTriangle takes about a quater of a milisecond on a decent size triangle (at least 100 x 100 square)

function InRangeBetter(Value, Border1, Border2: Integer): Boolean;
begin
Result := InRange(Value, Border1, Border2) or InRange(Value, Border2, Border1);
end;

function XToY(X: Integer; Point1, Point2: TPoint): Integer;
var
M: Extended;
begin
M := 1.0 * (Point2.y - Point1.y) / (Point2.x - Point1.x);
Result := Round((X - Point1.x) * M) + Point1.y;
end;

function PointInTriangle(ThePoint: TPoint; TrianglePoint1, TrianglePoint2, TrianglePoint3: TPoint): Boolean;
var
Error: Boolean;
begin
if not InRange(ThePoint.x, Min(Min(TrianglePoint1.x, TrianglePoint2.x), TrianglePoint3.x), Max(Max(TrianglePoint1.x, TrianglePoint2.x), TrianglePoint3.x)) then
Exit;
if ((TrianglePoint1.x < ThePoint.x) and (TrianglePoint2.x < ThePoint.x)) or ((TrianglePoint1.x > ThePoint.x) and (TrianglePoint2.x > ThePoint.x)) then
Result := InRangeBetter(ThePoint.y, XToY(ThePoint.x, TrianglePoint1, TrianglePoint3), XToY(ThePoint.x, TrianglePoint2, TrianglePoint3)) else
if ((TrianglePoint1.x < ThePoint.x) and (TrianglePoint3.x < ThePoint.x)) or ((TrianglePoint1.x > ThePoint.x) and (TrianglePoint3.x > ThePoint.x)) then
Result := InRangeBetter(ThePoint.y, XToY(ThePoint.x, TrianglePoint1, TrianglePoint2), XToY(ThePoint.x, TrianglePoint2, TrianglePoint3)) else
if ((TrianglePoint2.x < ThePoint.x) and (TrianglePoint3.x < ThePoint.x)) or ((TrianglePoint2.x > ThePoint.x) and (TrianglePoint3.x > ThePoint.x)) then
Result := InRangeBetter(ThePoint.y, XToY(ThePoint.x, TrianglePoint1, TrianglePoint2), XToY(ThePoint.x, TrianglePoint1, TrianglePoint3)) else
if ThePoint.x = TrianglePoint1.x then
begin
if InRangeBetter(TrianglePoint1.x, TrianglePoint2.x, TrianglePoint3.x) then
Result := InRangeBetter(ThePoint.y, TrianglePoint1.y, XToY(ThePoint.x, TrianglePoint2, TrianglePoint3)) else
Result := ThePoint.y = TrianglePoint1.y;
end else
if ThePoint.x = TrianglePoint2.x then
begin
if InRangeBetter(TrianglePoint2.x, TrianglePoint1.x, TrianglePoint3.x) then
Result := InRangeBetter(ThePoint.y, TrianglePoint2.y, XToY(ThePoint.x, TrianglePoint1, TrianglePoint3)) else
Result := ThePoint.y = TrianglePoint1.y;
end else
if ThePoint.x = TrianglePoint3.x then
begin
if InRangeBetter(TrianglePoint3.x, TrianglePoint1.x, TrianglePoint2.x) then
Result := InRangeBetter(ThePoint.y, TrianglePoint3.y, XToY(ThePoint.x, TrianglePoint1, TrianglePoint2)) else
Result := ThePoint.y = TrianglePoint1.y;
end;
end;

function RandomPointInTriangle1(TrianglePoint1, TrianglePoint2, TrianglePoint3: TPoint): TPoint;
var
Counter, X, Y: Integer;
TPA: TPointArray;
begin
for Counter := 1 to 100 do
begin
X := RandomRange(Min(Min(TrianglePoint1.x, TrianglePoint2.x), TrianglePoint3.x), Max(Max(TrianglePoint1.x, TrianglePoint2.x), TrianglePoint3.x) + 1);
Y := RandomRange(Min(Min(TrianglePoint1.y, TrianglePoint2.y), TrianglePoint3.y), Max(Max(TrianglePoint1.y, TrianglePoint2.y), TrianglePoint3.y) + 1);
if PointInTriangle(Point(X, Y), TrianglePoint1, TrianglePoint2, TrianglePoint3) then
begin
Result := Point(X, Y);
Exit;
end;
end;
end;