Libraryless. Click here for Pure Java version (11542L/65K).
1 | // both the outer outline and the outline of a hole are called a "trace" |
2 | // should return outer outline first and then outline of holes |
3 | |
4 | // seems to return first point again at the end sometimes |
5 | |
6 | srecord noeq RegionBorder_innerPoints(BWImage_FastRegions regions, int iRegion) extends AbstractSteppable { |
7 | event newTrace(bool isHole); |
8 | event foundPoint(Pt p); |
9 | event traceDone; |
10 | |
11 | int w, x, y, dir; |
12 | BWImage_FastRegions.RegionIterator it; |
13 | byte[] reachedInDirections; // bits 0 to 3 |
14 | bool tracing; |
15 | gettable bool tracingHole; |
16 | |
17 | // directions (0 = right, 1 = down, 2 = left, 3 = up) |
18 | static Pt[] directions = { |
19 | pt(1, 0), pt(0, 1), pt(-1, 0), pt(0, -1) // r, d, l, u |
20 | }; |
21 | |
22 | void init { |
23 | w = regions.w; |
24 | reachedInDirections = new byte[w*regions.h]; |
25 | it = regions.regionIterator(iRegion); |
26 | } |
27 | |
28 | public bool step() { |
29 | if (reachedInDirections == null) init(); |
30 | |
31 | if (tracing) { |
32 | int pos = y*w+x; |
33 | if ((reachedInDirections[pos] & (1 << dir)) != 0) { |
34 | traceDone(); |
35 | tracing = false; |
36 | true; |
37 | } |
38 | |
39 | reachedInDirections[pos] |= (byte) 1 << dir; |
40 | foundPoint(x, y); |
41 | |
42 | for (int turn = 3; turn <= 6; turn++) { // try left, straight, right, back |
43 | int newDir = (dir+turn) & 3; |
44 | Pt d = directions[newDir]; |
45 | int x2 = x+d.x, y2 = y+d.y; |
46 | bool b = regions.inRegion(iRegion, x2, y2); |
47 | ifdef RegionBorder_innerPoints_debug |
48 | printVars(+x, +y, +dir, +turn, +newDir, +x2, +y2, +b); |
49 | endifdef |
50 | if (b) { |
51 | x = x2; y = y2; dir = newDir; |
52 | true; |
53 | } |
54 | } |
55 | |
56 | true; // i think this ends the trace in next iteration |
57 | } else { |
58 | // search for first border pixel |
59 | |
60 | if (!it.next()) false; // done |
61 | x = it.x(); y = it.y(); |
62 | |
63 | if (reachedInDirections[y*w+x] != 0) true; // seen pixel before |
64 | |
65 | // if pixel above is empty, walk to the right |
66 | if (!regions.inRegion(iRegion, x, y-1)) |
67 | ret true with startTrace(0); |
68 | |
69 | // if pixel on the left is empty, walk upwards |
70 | if (!regions.inRegion(iRegion, x-1, y)) |
71 | ret true with startTrace(3); |
72 | |
73 | // if pixel on the right is empty, walk downwards |
74 | if (!regions.inRegion(iRegion, x+1, y)) |
75 | ret true with startTrace(1); |
76 | |
77 | // if pixel below is empty, walk left |
78 | if (!regions.inRegion(iRegion, x, y+1)) |
79 | ret true with startTrace(2); |
80 | |
81 | // not a border pixel, continue search |
82 | true; |
83 | } |
84 | } |
85 | |
86 | void startTrace(int dir) { |
87 | this.dir = dir; |
88 | |
89 | // mark point reached from all directions in next step |
90 | reachedInDirections[y*w+x] = (byte) (15 & ~(1 << dir)); |
91 | |
92 | set tracing; |
93 | newTrace(tracingHole); |
94 | set tracingHole; |
95 | } |
96 | |
97 | void foundPoint(int x, int y) { foundPoint(pt(x, y)); } |
98 | |
99 | // get all points as list |
100 | |
101 | simplyCached L<Pt> allPoints() { |
102 | new PtBuffer l; |
103 | onFoundPoint(p -> l.add(p)); |
104 | run(); |
105 | ret l; |
106 | } |
107 | |
108 | // get outline as OnePath |
109 | |
110 | simplyCached OnePath onePath() { |
111 | ret new OnePath(allPoints(), true); |
112 | } |
113 | |
114 | // for debugging |
115 | void runAndPrint { |
116 | onNewTrace(hole -> print(!hole ? "new outline" : "new hole")); |
117 | onTraceDone(-> print("traceDone")); |
118 | onFoundPoint(p -> print("foundPoint " + p)); |
119 | stepMaxWithStats(this, 10000); |
120 | } |
121 | } |
Began life as a copy of #1033938
download show line numbers debug dex old transpilations
Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033941 |
Snippet name: | RegionBorder_innerPoints - use RegionBorder_innerPoints_v2 instead |
Eternal ID of this version: | #1033941/33 |
Text MD5: | b5f4842adf5875eddd5a31df2f0e4460 |
Transpilation MD5: | 3b36e55e10ea060a05a582da80c83800 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-03-14 17:15:46 |
Source code size: | 3452 bytes / 121 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 226 / 443 |
Version history: | 32 change(s) |
Referenced in: | [show references] |