8000 more test cases and edge cases · dragoncoder047/schemascii@e001396 · GitHub
[go: up one dir, main page]

Skip to content

Commit e001396

Browse files
more test cases and edge cases
1 parent 04ebdce commit e001396

File tree

1 file changed

+81
-26
lines changed

1 file changed

+81
-26
lines changed

test_data/blob_test.py

Lines changed: 81 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@
6363
#
6464
#""",
6565
"""
66+
######
67+
########
68+
#########
69+
##########
70+
#########
71+
########
72+
######""",
73+
"""
6674
###########
6775
#############
6876
###############
@@ -72,7 +80,14 @@
7280
#### ####
7381
###############
7482
#############
75-
###########"""]
83+
###########""",
84+
"""
85+
###############
86+
###################""",
87+
"""
88+
###############
89+
###################
90+
###############"""]
7691

7792
"""
7893
idea for new algorithm
@@ -133,6 +148,11 @@ def triples(v: list[T]) -> list[tuple[T, T, T]]:
133148
return list(zip(cir(v, False), v, cir(v, True)))
134149

135150

151+
def fiveles(v: list[T]) -> list[tuple[T, T, T]]:
152+
x, y, z = cir(v, False), v, cir(v, True)
153+
return list(zip(cir(x, False), x, y, z, cir(z, True)))
154+
155+
136156
def cull_disallowed_edges(
137157
all_points: list[complex],
138158
edges: dict[complex, set[complex]]) -> dict[complex, set[complex]]:
@@ -147,16 +167,18 @@ def cull_disallowed_edges(
147167
# if there are multiple directions out of here, find the gaps and
148168
# only keep the ones on the sides of the gaps
149169
gaps = [p1 + d in all_points for d in DIRECTIONS]
150-
tran_5 = list(zip(
151-
cir(cir(gaps, False), False),
152-
cir(gaps, False),
153-
gaps,
154-
cir(gaps, True),
155-
cir(cir(gaps, True), True)))
170+
tran_5 = fiveles(gaps)
156171
# im not quite sure what this is doing
157172
fixed_edges[p1] = set(p1 + d for (d, (q, a, b, c, w))
158173
in zip(DIRECTIONS, tran_5)
159174
if b and not ((a and c) or (q and w)))
175+
# ensure there are no one way "trap" edges
176+
# (the above algorithm has some weird edge cases where it may produce
177+
# one-way edges on accident)
178+
# XXX This causes issues when it is enabled, why?
179+
for p1 in all_points:
180+
for p2 in fixed_edges.setdefault(p1, set()):
181+
fixed_edges.setdefault(p2, set()).add(p1)
160182
return fixed_edges
161183

162184

@@ -174,7 +196,7 @@ def walk_graph_to_loop(
174196
# log the direction we came from
175197
swd_into.setdefault(current, set()).add(current_dir)
176198
choices_directions = (rot(current_dir, i)
177-
for i in (-1, 1, -2, 2, -3, 3, 0, 4))
199+
for i in (-1, -2, -3, 0, 1, 2, 3, 4))
178200
bt_d = None
179201
for d in choices_directions:
180202
# if allowed to walk that direction
@@ -202,13 +224,21 @@ def walk_graph_to_loop(
202224
return out
203225

204226

227+
def is_mid_maxima(a: int | None, b: int | None, c: int | None) -> bool:
228+
return all(x is not None for x in (a, b, c)) and a < b and c < b
229+
230+
205231
def remove_unnecessary(pts: list[complex],
206-
edges, maxslope=2) -> list[complex]:
232+
edges: dict[complex, set[complex]],
233+
maxslope=2) -> list[complex]:
207234
triples_pts = list(triples(pts))
208235
dirs = [(b-a, c-b) for a, b, c in triples_pts]
209236
signos = [a.real * b.imag - a.imag * b.real
210237
+ (abs(b - a) if a == b or a == -b else 0) for a, b in dirs]
211238
# signos: 0 if straightline, negative if concave, positive if convex
239+
dotnos = [a.real * b.real + a.imag * b.imag for a, b in dirs]
240+
# dotnos: a measure of pointedness - 0 = right angle, positive = pointy,
241+
# negative = blunt
212242
distances = [None if s >= 0 else 0 for s in signos]
213243
# distances: None if it's a convex or straight un-analyzed,
214244
# number if it's a concave or counted straight
@@ -236,46 +266,71 @@ def remove_unnecessary(pts: list[complex],
236266
# at this point, distances should contain:
237267
# None for the convex points
238268
# numbers for all others
239-
points_to_keep = set(p for p, s, (a, b, c) in zip(
240-
pts, signos, triples(distances))
241-
if (b is None and s != 0) # keep all convex points
242-
or ((a is not None and a < b) # keep all the local maxima
243-
and (c is not None and c < b))
244-
or (b is not None and b > maxslope)) # keep ones that are flat enough
245-
assert len(points_to_keep) > 0
269+
maxima = [is_mid_maxima(a, b, c) for (a, b, c) in triples(distances)]
270+
points_to_maybe_discard = set(
271+
pt for (pt, dist, maxima) in zip(pts, distances, maxima)
272+
# keep all the local maxima
273+
# keep ones that are flat enough
274+
# --> remove the ones that are not sloped enough
275+
# and are not local maxima
276+
if ((dist is not None and dist < maxslope)
277+
and not maxima))
278+
# the ones to definitely keep are the convex ones
279+
# as well as concave ones that are adjacent to only straight ones that
280+
# are being deleted
281+
points_to_def_keep = set(p for p, s in zip(pts, signos)
282+
if s > 0
283+
or (s < 0 and all(
284+
signos[z := pts.index(q)] == 0
285+
and q in points_to_maybe_discard
286+
for q in edges[p])))
287+
# special case: keep concave ones that are 2-near at
288+
# least one convex pointy point (where pointy additionally means that
289+
# it isn't a 180)
290+
points_to_def_keep |= set(
291+
p for (
292+
p,
293+
(dot_2l, _, _, _, dot_2r),
294+
(sig_2l, _, sig_m, _, sig_2r),
295+
((dd1_2l, dd2_2l), _, _, _, (dd1_2r, dd2_2r))
296+
) in zip(pts, fiveles(dotnos), fiveles(signos), fiveles(dirs))
297+
if sig_m < 0 and (
298+
(sig_2l > 0 and dot_2l < 0 and dd1_2l != -dd2_2l)
299+
or (sig_2r > 0 and dot_2r < 0 and dd1_2r != -dd2_2r)))
246300
# for debugging
247301
a = dots([], edges)
248302
i = a.replace("</svg>", "".join(f"""<circle cx="{
249303
p.real
250304
}" cy="{
251305
p.imag
252-
}" r="{
253-
q / 5 if isinstance(q, int)
254-
else 0
255-
}" fill="{
306+
}" r="0.5" fill="{
256307
"red" if r > 0
257308
else "blue" if r < 0
258309
else "black"
259310
}" opacity="50%"></circle>"""
260-
for p, q, r in zip(pts, distances, signos)) + "</svg>")
311+
for p, q, r in zip(pts, distances, dotnos)) + "</svg>")
261312
z = a.replace("</svg>", "".join(f"""<circle cx="{
262313
p.real
263314
}" cy="{
264315
p.imag
265316
}" r="0.5" fill="red" opacity="50%"></circle>"""
266-
for p in points_to_keep) + "</svg>")
317+
for p in (points_to_maybe_discard - points_to_def_keep)) + "</svg>")
267318
print("begin conc", i, "end conc")
268-
print("begin keep", z, "end keep")
319+
print("begin discard", z, "end discard")
269320
# end debugging
270-
return [p for p in pts if p in points_to_keep]
321+
return [p for p in pts
322+
if p not in points_to_maybe_discard
323+
or p in points_to_def_keep]
271324

272325

273326
def process_group(g: list[complex], all_pts: list[complex]) -> list[complex]:
274327
edges = cull_disallowed_edges(all_pts, points_to_edges(g))
275328
print(dots(g, edges))
329+
start = min(g, key=lambda x: x.real * 65536 + x.imag)
330+
next = min(edges[start], key=lambda x: x.real * 65536 - x.imag)
276331
g = walk_graph_to_loop(
277-
start=min(g, key=lambda x: x.real * 65536 + x.imag),
278-
start_dir=1j,
332+
start=start,
333+
start_dir=next - start,
279334
edges=edges)
280335
g = remove_unnecessary(g, edges)
281336
return g

0 commit comments

Comments
 (0)
0