SRL Archive - Help and Support

Searching or Setting and Irregular Shape.


Special Ed

2007-10-27 01:18:49

Question for you all, although it may not be in the boundries of SCAR it would be nice to know. Does anyone have an idea as how to (a) Search in an irregular Polygonal Box (i.e. 7 Points, Random Distances) and (b) how to Set an irregular polygon.

I was thinking of using Types like this…

Polygon.Point[0].x:= ;
Polygon.Point[0].y:= ;

but all that would do is set a few points, It wouldn't get me any closer to my goal although it could be used in making something that works for what I'm trying to do.

Basically, how do you find a color in an irregular polygon, and how do you set an irregular polygons' edges.

R0b0t1

2007-10-27 01:45:19

If you wanted pre-existing functions, you could use division to split the polygons up into a series of triangles and rectangles.


FindColorTriangle(...);

Dark_Sniper

2007-10-27 01:52:42

so wait…

image of what i think u r thinking:


is that what you want to do?


@robot1


he said irregular….

Santa_Clause

2007-10-27 01:57:40

Irregular can still be split up into a bunch of triangles…

mastaraymond

2007-10-27 04:46:35

Its possible but in scar its going to be very slow.. Benland made a function like this for SRL, its like if x > x1 and x > x19 etc…. You could do it by setting all the corner points, then searching the common x and common y, then check if those are in the box.. Its not really hard to make and maybe in a plugin quite fast to.

~Raymond

n3ss3s

2007-10-27 06:29:16

Well I know a way, but that'd be really slow propably, just get every single point of the polygon edges and then search in "lines" =/ Once actually tried…

mastaraymond

2007-10-27 06:33:22

From: n3ss3s
Well I know a way, but that'd be really slow propably, just get every single point of the polygon edges and then search in "lines" =/ Once actually tried…
Meh, thats exactly what i stated above ;).

First of all you should get the rough edges of the whole box.. If its not in that box, return false. Then you just need to search the same line and check if the point is in this line ;). Its ofcourse slower then IntInBox, but if you put it in a Pluggy, you can get a good speed.

~Raymond

SKy Scripter

2007-10-27 11:05:29

From: SKy Scripter


first one it detects 3 sides.

second one it detects 2 sides.

third one it detects 4 sides.

you can tell if its a circle or not by how points it gives off.

program new;
const
ShapeColor = 1781050;
MinArea = 10; // The Min Area of the corner.
UseFastFlood = True;


var
Pixels : record
P : TPointArray;
Colors : TIntegerArray;
Corner : array of boolean;
end;
ax, ay : TIntegerArray;
Canvas : TCanvas;
Area, bgcolor, newcolor, q : Integer;


procedure FindEdge(x, y, i : Integer);
var p,n : Integer;
begin
for n := 0 to q do
if (InRange(x + ax[n], 0, 100))
and (InRange(y + ay[n], 0, 100)) then
begin
p := canvas.pixels[x + ax[n], y + ax[n]];
if (p <> clred) and (p <> clgreen) then
begin
Canvas.pixels[x, y] := 255;
Pixels.Corner[i] := True;
end;
end;
end;


procedure floodfill(x, y: Integer);
var n : Integer;
begin
for n := 0 to q do
if (InRange(x + ax[n], 0, 100))
and (InRange(y + ay[n], 0, 100)) then
if (Canvas.Pixels[x + ax[n],y + ay[n]] = bgcolor) then
begin
Area := area + 1;
Canvas.Pixels[x + ax[n],y + ay[n]] := newcolor;
floodfill(x + ax[n],y + ay[n]);
end;
end;




var
T : TPointArrayArray;
I, mx, my, D, ad, c, cnr: Integer;

begin
Ax := [1, 0, -1, 0, 1, 1, -1, -1];
Ay := [0, 1, 0, -1, -1, 1, 1, -1];
if UseFastFlood then q := 3 else q := 7;
DisplayDebugImgwindow(100, 100);
Canvas := GetDebugCanvas;
SafeCopyCanvas(GetClientCanvas, Canvas, 0, 0, 100, 100, 0, 0, 100, 100);
findcolorstolerance(Pixels.P, ShapeColor, 0, 0, 100, 100, 18); // 1385775, 30
T := SplitTPA(Pixels.P);
Pixels.P := BiggestGroup(T);
MiddleTPAEx(Pixels.P, mx, my);
if (Length(Pixels.P)=0) then begin Writeln('found nothing'); Exit; end;
SetArrayLength(Pixels.Corner, Length(Pixels.p));
SetArrayLength(Pixels.Colors, Length(Pixels.p));


for I := 0 to Length(Pixels.P)-1 do
begin
Pixels.Colors[i] := Canvas.Pixels[Pixels.P[i].x, Pixels.P[i].y];
Canvas.Pixels[Pixels.P[i].x, Pixels.P[i].y] := 255;
end;


for i := 0 to length(Pixels.p)-1 do
begin
FindEdge(Pixels.P[i].x, Pixels.P[i].y, i);
if (Pixels.Corner[i]) then
begin
D := Distance(Pixels.P[i].x, Pixels.P[i].y, mx, my);
ad := ad + d;
inc(c);
end;
end;

ad := ad / c;

for i := 0 to length(Pixels.p)-1 do
begin
if (not (Distance(Pixels.P[i].x, Pixels.P[i].y, mx, my) > ad)) then
Canvas.Pixels[Pixels.P[i].x, Pixels.P[i].y] := -1;
end;

for i := 0 to length(Pixels.p)-1 do
begin
Area := 0;
bgcolor := 255;
newcolor := clblue;
if Pixels.Corner[i] then
if (Canvas.Pixels[Pixels.P[i].x, Pixels.P[i].y] <> ClBlue) then
begin
FloodFill(Pixels.P[i].x, Pixels.P[i].y);
if (Area > MinArea) then inc(cnr)
end;
end;

Canvas.Pixels[mx, my] := Clwhite;
Writeln(inttostr(cnr) + ' sides');

end.



Edit : this is how it looks with the locks..



[ATTACH]7755[/ATTACH]

- The Keys


-The Locks

Heres how i do it

Special Ed

2007-10-27 12:51:11

Thanks for those links that I can't access Sky… I would like to at least know what they are.

As for the function in code above it… I g2g for now but I'll look into it.

SKy Scripter

2007-10-27 13:03:48

these are the pics…

[ATTACH]7896[/ATTACH]

[ATTACH]7897[/ATTACH]

Special Ed

2007-10-27 23:47:02

Hmmm… those aren't really irregular shapes they're just squares and triangles, not necessarily what I'm looking for, but thanks though.

Bobarkinator

2007-10-28 18:46:41

{*******************************************************************************
function InAbstractBox(x1, y1, x2, y2, x3, y3, x4, y4: Integer; x, y: Integer): Boolean;
By: BenLand100
Description: Returns true if point x, y is in an abstract box defined by x1, y1, x2, y2, x3, y3, x4, y4
An abstract box example:

x1, y1 x2, y2
+--------+
\ /
\ /
+--+
x4, y4 x3, y3
*******************************************************************************}

function InAbstractBox(x1, y1, x2, y2, x3, y3, x4, y4: Integer; x, y: Integer):
Boolean;
var
U, D, R, L: Boolean;
UB, DB, LB, RB, UM, DM, LM, RM: Extended;
begin
UM := (-y1 - -y2) div (x1 - x2);
DM := (-y4 - -y3) div (x4 - x3);
if x1 - x4 <> 0 then
begin
LM := (-y1 - -y4) div (x1 - x4);
end else
begin
LM := Pi;
end;
if x2 - x3 <> 0 then
begin
RM := (-y2 - -y3) div (x2 - x3);
end else
begin
RM := Pi;
end;
UB := -(UM * x1) + -y1
RB := -(RM * x2) + -y2;
DB := -(DM * x3) + -y3;
LB := -(LM * x4) + -y4;
if (UM * x + UB >= -y) then U := True;
if (DM * x + DB <= -y) then D := True;
if (RM <> Pi) and (RM >= 0) and (RM * x + RB <= -y) then R := True;
if (RM <> Pi) and (RM < 0) and (RM * x + RB >= -y) then R := True;
if (RM = Pi) and (x < x2) then R := True;
if (LM <> Pi) and (LM >= 0) and (LM * x + LB >= -y) then L := True;
if (LM <> Pi) and (LM < 0) and (LM * x + LB <= -y) then L := True;
if (LM = Pi) and (x > x1) then L := True;
if U and D and L and R then Result := True;
end;

Variation for 7 sides?

Special Ed

2007-10-28 19:50:48

@ Bob - Whaaa? What are you talking about, thats only good for boxes… and what do you mean variation for 7 sides.

Bobarkinator

2007-10-28 19:55:40

Look at the code, you set 4 coordinates and it will search the area in the shape you made, basically any polygon. I was saying you could edit it so you inputed 7 coordinates and it would search the area of that shape.

Special Ed

2007-10-28 21:30:35

I can't think tonight, I just don't get it, I guess I could see how you could change the code but would it work?

Boreas

2007-10-28 23:12:47

Can you guarantee that there will be no concave corners?

Special Ed

2007-10-29 19:38:34

Ummm… no, I was basically looking for something that will work with finding the edges of a Rock… I'm not looking for Benlands edge finder Its just some key points on the rock that I'd like to work with. and I need the area within it.

mat_de_b

2007-10-29 22:31:50

@sky how do you know when to look for the shape? count color?

SKy Scripter

2007-10-29 23:24:25

Well the pixels length is the area.
so thats the color counting…


im sure you could use a DTM for this..

im really not sure what you want Special Ed.
but Cant you just use
FindColorAbstract() ?

Special Ed

2007-10-29 23:46:34

Well what I am trying to do, is I've developed a method of "counting" the colors in a Rock for mining, but the problem is, is that after it gets to the "gaps" in the old rocks (when they're right next to each other) it doesn't stop, So the only way I can prevent that is to make it do more searches in smaller areas creating a lot of lag, but if I can make an abstract polygon (i need like 7 sides or something) I can make it stop searching when the distance from the two middle points are "x" so that it doesn't keep searching into other rocks and return a huge area.

Basically I just need it so that my procedure that I'm working on will find 1 Rock when there are multiple next to each other. Its very efficient so far besides that part.

Boreas

2007-10-30 02:21:47

TPAtoATPA?

n3ss3s

2007-10-30 09:31:47

TPAtoATPA?
Rofl owned.

Btw bob, "Points: TPointArray" much? So you could then make the function decide by the length of the array that what to do etc..

mastaraymond

2007-10-30 11:12:12

From: n3ss3s
Rofl owned.

Btw bob, "Points: TPointArray" much? So you could then make the function decide by the length of the array that what to do etc..

You could also just eat cookies..

SKy Scripter

2007-10-30 11:37:01

somthing like that, i was in a hurry.


function ReturnRocks(Color : Integer; Hue, Sat, Lum : Extended) : TPointArray;
var t : Tpointarrayarray;
P : TPointArray;
i : Integer;
begin
ColorToleranceSpeed(2);
SetColorspeed2Modifiers(Hue, Sat);
FindColorstolerance(p, 5, 5, MSX2-5, MSY2-5, trunc(lum));
t := SplitTPAex(p, 15, 15);
setlength(result,length(t));
for i := 0 to length(t)-1 do
Result := MiddleTPA(t[i]);
end;

Special Ed

2007-10-30 18:19:39

Yea I figured that out today pondering over it, but I still need to be able to figure out the area within the points… Thats the main problem I'm having now. I was asking people about it today and no-one I talked too knew how to find the area of an abstract polygon… TO GOOGLE!

EDIT: Gah… Google fails… 30 pages and not 1 thing telling me what I want, Benland probably knows I'll ask him.

SKy Scripter

2007-10-30 20:46:26

Flood Fill ;) thats always the answer!! for abstract stuff.

R0b0t1

2007-10-30 21:44:21

I think you are looking for things in the C++ category.

Town

2007-10-30 23:10:49

I'm in the process of making "function FindColorInPoly(var x, y: Integer; Color: Integer; Lines: Array of Array of TPointArray; Tol: Integer): Boolean;" now. . . I would finish it up now but I feel like going to bed. I'll post it tomarrow, it's pretty cool.

Special Ed

2007-10-30 23:19:18

See thats what I need. Except I really need FindColorsPoly, but I can make that happen if I have the groundwork…

Miitchyy

2007-10-31 07:52:23

Couldn't you like, Make a TCanvas, Plot all the outside lines, Get the middle point, Using Hypot get the angle and draw a line then (Since it was all draw in a specific color) Change the target handle to the canvas's and then get all the points of the colors then check all those points for the color?



Or get the middle of the TPA and make triangles between the points?

EDIT:
function FindColorPolys(var x, y: Integer; Color: Integer; Points: TPointArray): Boolean;
var
Tx, Ty, Bx, By, I: Integer;
Mid: TPoint;
begin
Mid := MiddleTPA(Points);
for I := 0 to GetArrayLength(Points) - 1 do
begin
if (I = GetArrayLength(Points) - 1) then
begin
Bx := Points[0].X;
By := Points[0].Y;
end else
begin
Bx := Points[I + 1].X;
By := Points[I + 1].Y;
end;
if FindColorTriangle(Tx, Ty, Color, Mid.X, Mid.Y, Points[I].X, Points[I].Y, Bx, By) then
Break;
end;
if (Tx > -1) and (Ty > -1) then
begin
Result := True;
X := Tx;
Y := Ty;
end;
end;

But, It only works with basic polygons: See below

Special Ed

2007-10-31 16:17:22

*Sigh…* Also for your triangle theory…
  • Doesn't have a constant edge color
  • I'd have to plot the lines myself
  • How can I find the middle if i need the function to find the middle?

So that wouldn't work… sadly… Although I have a theory that may work, I just need to figure out how to program it, lol.

The problem is that it is getting to many points… I need it to search for the points within the polygon not to make the polygon…

Town

2007-10-31 18:13:28

From: Special Ed
See thats what I need. Except I really need FindColorsPoly, but I can make that happen if I have the groundwork…


function FindColorInPoly(var Points: TPointArray; Color: Integer; Lines: Array of Array of Integer; Tol: Integer): Boolean;
var
Slope: TPointArray;
Current, p, y, i, X1, X2, Y1, Y2: Integer;
Pointss: TPointArray;
Cross: Array of Array of Boolean;
begin
SetArrayLength(Slope, GetArrayLength(Lines));
for i := 0 to GetArrayLength(Lines) - 1 do
begin
Slope[i].x := Lines[i][0] - Lines[i][2];
Slope[i].y := Lines[i][1] - Lines[i][3];
end;
for i := 0 to GetArrayLength(Lines) - 1 do
begin
if (i = 0) then
begin
X1 := Lines[i][0];
Y1 := Lines[i][1];
X2 := Lines[i][2];
Y2 := Lines[i][3];
i := i + 1;
end;
if (Lines[i][0] < X1) then X1 := Lines[i][0];
if (Lines[i][2] < X1) then X1 := Lines[i][2];
if (Lines[i][1] < Y1) then Y1 := Lines[i][1];
if (Lines[i][3] < Y1) then Y1 := Lines[i][3];
if (Lines[i][2] > X2) then X2 := Lines[i][2];
if (Lines[i][0] > X2) then X2 := Lines[i][0];
if (Lines[i][3] > Y2) then Y2 := Lines[i][3];
if (Lines[i][1] > Y2) then Y2 := Lines[i][1];
end;
// WriteLN('X1: ' + IntToStr(X1) + ' Y1: ' + IntToStr(Y1) + ' X2: ' + IntToStr(X2) + ' Y2: ' + IntToStr(Y2));
FindColorsTolerance(Pointss, Color, X1, Y1, X2, Y2, Tol);
// WriteLN(IntToStr(GetArrayLength(Pointss)));
if (GetArrayLength(Pointss) = 0) then Exit;
// WriteLN('');
SetArrayLength(Cross, GetArrayLength(Pointss));
for p := 0 to GetArrayLength(Cross) - 1 do
SetArrayLength(Cross[p], GetArrayLength(Lines));
for p := 0 to GetArrayLength(Pointss) - 1 do
begin
for i := 0 to GetArrayLength(Lines) - 1 do
begin
if (Pointss[p].y > Lines[i][1]) and (Pointss[p].y > Lines[i][3]) then
begin
Cross[p][i] := True;
end else
begin
if (Pointss[p].y > Lines[i][1]) or (Pointss[p].y > Lines[i][3]) then
begin
try
if (Lines[i][1] > Lines[i][3]) then y := ((Lines[i][1] - Pointss[i].y) / Slope[i].y)
else y := ((Lines[i][3] - Pointss[i].y) / Slope[i].y);
except
end;
if (Lines[i][0] < Lines[i][2]) then
begin
if (Lines[i][0] + (Slope[i].x * y) = Pointss[p].x) then
begin
Cross[p][i] := True;
end;
end else
begin
if (Lines[i][2] + (Slope[i].x * y) = Pointss[p].x) then
begin
Cross[p][i] := True;
end;
end;
end;
end;
end;
end;
for p := 0 to GetArrayLength(Pointss) - 1 do
begin
for i := 0 to GetArrayLength(Lines) - 1 do
if (Cross[p][i]) then Current := Current + 1;
// WriteLN(IntToStr(Current));
if (Current mod 2 <> 0) then
begin
SetArrayLength(Points, GetArrayLength(Points) + 1);
Points[GetArrayLength(Points) - 1] := Pointss[p];
end;
Current := 0;
end;
if (GetArrayLength(Points) > 0) then Result := True;
end;

It may be a little buggy. If it pops up with any runtime errors or anything tell me. It worked correctly like this:

var
Lines: Array[0..5] of Array of Integer;
Points: TPointArray;
i: Integer;
begin
Lines[0] := [215, 138, 392, 225];
Lines[1] := [392, 225, 423, 225];
Lines[2] := [423, 225, 443, 234];
Lines[3] := [443, 234, 425, 241];
Lines[4] := [425, 241, 393, 240];
Lines[5] := [393, 240, 215, 138];
if (FindColorInPoly(Points, 6491917, Lines, 1)) then WriteLN('yes');
for i := 0 to GetArrayLength(Points) - 1 do
WriteLN('x: ' + IntToStr(Points[i].x) + ' y: ' + IntToStr(Points[i].y));
end.

I don't think it will return the coordinates of it is on top of a line but I can fix that if it makes a difference.

If you don't understand whatsoever how I made that function, read this: http://en.wikipedia.org/wiki/Point_in_polygon.

– I have some time so I'll explain how it works (or should work, I'm pretty sure I messed something up):

(0, 1) and (2, 3) makes a line. All of those lines make the polygon. First, I make a square that will pull up some coordinates that are outside of the polygon but will make a starting array. Then, I sort through the array by counting the number of lines it crosses going down the y axis until it is out of the polygon. If that number is odd then it is in the polygon, if the number is even then it is out of the polygon.

Special Ed

2007-10-31 18:36:54

Interesting… Thanks for the effort I'll see if it will work for what I want it to, or If I can make it so it does.

EDIT: Yea! Kudos man it works like a charm, the only suggestion I have for it is in its thread so look there.

Miitchyy

2007-11-01 07:20:05

Not trying to be an ass or anything;
It isn't very efficient and could be shortened, Also, It missing some points

And I don't get what you said in reply to mine?
Constant edge?
Ofcourse you need to know the points your searching in?
There's a functoin to find the middle point in SCAR <__>?
Although, Towns is the best there is for what your looking for because there is no way for mine to COUNT the colors also very ingenious o_O

The Claw

2007-11-01 08:23:26

Why do you need to know the exact amount of points for rockfinding? But even if you did want the exact amount, floodfilling would probably be more accurate and efficient than creating a weird shape and searching in that. :)

n3ss3s

2007-11-01 10:01:59

There's a functoin to find the middle point in SCAR <__>?


SRL/SRL/Misc/WizzyPlugin.scar ;) Ftw..



Umm I dont think things like rock finding dont require the exact points, I think you only need the width, height and a color of the rock.

R0b0t1

2007-11-01 18:27:21

I need to work on my awesomeness, you guys are all out-awesomeng me.


I think searching in a complex polygon could be cool… I might try it sometime.

neG

2007-11-02 01:55:13

From: SKy Scripter
these are the pics…

[ATTACH]7896[/ATTACH]

[ATTACH]7897[/ATTACH]


Pillory Solver ey?
Interesting..

Special Ed

2007-11-03 13:01:47

Well its not just for the rock finding, although thats its main purpose. Depending on what I can get to run fast / more efficient will determine what I use in this function. It was just an idea though, so I expected it to have some problems with it, I didn't expect people to be so negative about it.

R0b0t1

2007-11-03 17:24:04

What? I'm not negative. I'm actually working on something to this effect in C++. I'm just having problems seeing if it passes through the edge, which I can fix…


Once I finish, I could message you if you want.

R0b0t1

2007-11-03 17:25:22

What? I'm not negative. I'm actually working on something to this effect in C++. I'm just having problems seeing if it passes through the edge, which I can fix…


Once I finish, I could message you if you want.

Special Ed

2007-11-04 11:50:32

From: R0b0t1
What? I'm not negative. I'm actually working on something to this effect in C++. I'm just having problems seeing if it passes through the edge, which I can fix…


Once I finish, I could message you if you want.


Yea that would be awesome, don't rush it for me though, just take your time and make sure it works well.

R0b0t1

2007-11-04 12:09:27

I had no intention of rushing… The thing is pretty easy :p.



Is MSI still up?

Special Ed

2007-11-08 23:16:11

From: R0b0t1
I had no intention of rushing… The thing is pretty easy :p.



Is MSI still up?


Ummm… MSI Scripting Competition Anyone?

Also I'm working on the outline for the first project of MSI, its going to be amazing! Well… as long and people help with it… XD

As far as being on task, how are you coming with the C++ version?

R0b0t1

2007-11-09 17:06:57

I'm almost done with the hard part, getting the points on the line. Which boreas helped me with… Kinda.

Miitchyy

2007-11-09 19:56:21

I made one yesterday, In Delphi though, Works great with the only exception when I try to use the Polygon(Points: TPointArray): Integer; function in my plugin from SCAR it crashes

R0b0t1

2007-11-09 23:16:23

Heh. I could look at it if you want :p.


Proabably something stupid you know :p.