@@ -35,48 +35,75 @@ begin
3535end;
3636
3737
38- function TWebGraph._FindDoors(doors: T2DPointArray; white: TPointArray ): TRSDoorArray; static;
38+ function TWebGraph._FindDoors(doors: T2DPointArray; img: TImage ): TRSDoorArray; static;
3939var
40- direction, center: TPoint;
41- i: Integer;
40+ direction, inverted: TPoint;
41+ i, idx, j: Integer;
42+ doorType: ERSDoorType;
43+ splitA, splitB: Boolean;
4244begin
43- SetLength(Result, Length(doors));
44-
4545 for i := 0 to High(doors) do
4646 begin
47- center := doors[i].Mean();
48- Result[i].Center := center;
49-
50- if doors[i].Contains(center + [1,0]) and doors[i].Contains(center + [-1,0]) then
51- direction := [0,1]
52- else if doors[i].Contains(center + [0,1]) and doors[i].Contains(center + [0,-1]) then
53- direction := [1,0]
54- else if doors[i].Contains(center + [1,1]) and doors[i].Contains(center + [-1,-1]) then
55- direction := [1,-1]
56- else if doors[i].Contains(center + [1,-1]) and doors[i].Contains(center + [-1,1]) then
57- direction := [1,1]
58- else
59- Continue;
47+ case Length(doors[i]) of
48+ 4: doorType := ERSDoorType.NORMAL;
49+ 8: doorType := ERSDoorType.WIDE;
50+ else Continue;
51+ end;
6052
61- //check if pixels around the door are walkable to exclude weird objects colored red on the map as being doors
62- //also excludes open doors to be detected as doors needed to be passed through
63- if ((center + direction) in white) and ((center + direction.Rotate(180, [0,0])) in white) then
53+ with doors[i].Mean() do
6454 begin
65- Result[i].Direction := direction;
66- case Length(doors[i]) of
67- 4: Result[i].DoorType := ERSDoorType.NORMAL;
68- 8: Result[i].DoorType := ERSDoorType.WIDE;
69- end;
70- end;
55+ if (img.Pixel[X+1, Y] = $0000FF) or (img.Pixel[X-1, Y] = $0000FF) then
56+ direction := [0,1]
57+ else if (img.Pixel[X, Y+1] = $0000FF) or (img.Pixel[X, Y-1] = $0000FF) then
58+ direction := [1,0]
59+ else if (img.Pixel[X+1, Y+1] = $0000FF) or (img.Pixel[X-1, Y-1] = $0000FF) then
60+ direction := [1,-1]
61+ else if (img.Pixel[X+1, Y-1] = $0000FF) or (img.Pixel[X-1, Y+1] = $0000FF) then
62+ direction := [1,1]
63+ else
64+ Continue;
65+
66+ if (img.Pixel[X+direction.X, Y+direction.Y] <> $FFFFFF) or
67+ (img.Pixel[X + (direction.X*-1), Y+ (direction.Y*-1)] <> $FFFFFF) then
68+ Continue;
69+
70+ inverted := direction.Rotate(PI/2, [0,0]);
71+ splitA := False;
72+ splitB := False;
73+
74+ for j := 1 to 6 do
75+ with Point(X,Y) + (inverted * j) do
76+ case img.Pixel[X, Y] of
77+ $FFFFFF: Break;
78+ $333333, $0:
79+ begin
80+ splitA := True;
81+ Break;
82+ end;
83+ end;
7184
72- if Result[i].DoorType = ERSDoorType.WIDE then
73- case Result[i].Direction of
74- [0,1]: Result[i].Center.X -= 2;
75- [1,0]: Result[i].Center.Y -= 2;
76- end;
85+ for j := 1 to 6 do
86+ with Point(X,Y) - (inverted * j) do
87+ case img.Pixel[X, Y] of
88+ $FFFFFF: Break;
89+ $333333, $0:
90+ begin
91+ splitB := True;
92+ Break;
93+ end;
94+ end;
7795
78- Result[i].Before += Result[i].Center + Result[i].Direction * 2;
79- Result[i].After += Result[i].Center - Result[i].Direction * 2;
96+ if not splitA or not splitB then Continue;
97+
98+ idx := Length(Result);
99+ SetLength(Result, idx+1);
100+ Result[idx].Center := [X,Y];
101+ end;
102+
103+ Result[idx].DoorType := doorType;
104+ Result[idx].Direction := direction;
105+ Result[idx].Before := Result[idx].Center + direction * 2;
106+ Result[idx].After := Result[idx].Center - direction * 2;
80107 end;
81108end;
82109
@@ -101,7 +128,7 @@ This is an internal method. Don't use it if you don't know what you are doing.
101128*)
102129function TWebGraph._BuildGraph(map: TImage; white, red: TPointArray): TWebGraph; static;
103130var
104- a, b, i, j, n, len, hi, nonSepDoors : Integer;
131+ a, b, i, j, n, len, hi: Integer;
105132 atpa, parts: T2DPointArray;
106133 skeleton, nodes, tpa, doorsInTpa, doorNodes: TPointArray;
107134 bounds: TBox;
@@ -114,24 +141,15 @@ var
114141 doorPaths: T2DIntegerArray;
115142begin
116143 atpa := white.ClusterEx(1).SortBySize(True);
117- doors := TWebGraph._FindDoors(red.ClusterEx(1), white );
144+ doors := TWebGraph._FindDoors(red.ClusterEx(1), map );
118145
119146 for i := 0 to High(doors) do
120147 begin
121- door := doors[i];
122- if (door.DoorType = ERSDoorType.UNKNOWN) or atpa.InSameTPA(door.Before, door.After) then
123- begin
124- nonSepDoors += 1;
125- Continue;
126- end;
127-
128- door.SEPARATING := True;
129-
130- Result.Doors += door;
131- doorNodes += [door.Before, door.After];
148+ Result.Doors += doors[i];
149+ doorNodes += [doors[i].Before, doors[i].After];
132150 SetLength(doorPaths, Length(doorNodes));
133- doorPaths[(i-nonSepDoors) *2] += (i-nonSepDoors) *2+1;
134- doorPaths[(i-nonSepDoors) *2+1] += (i-nonSepDoors) *2;
151+ doorPaths[i *2] += i *2+1;
152+ doorPaths[i *2+1] += i *2;
135153 end;
136154
137155 for i := 0 to High(atpa) do
0 commit comments