def oracle_hausdorff_bounds2(recset1, recset2, f1, f2, eps=1e-1, k=3): refiner1 = edge_length_guided_refinement(recset1, f1) refiner2 = edge_length_guided_refinement(recset2, f2) while True: xs = list(fn.mapcat(lambda r: r.discretize(k), recset1)) ys = list(fn.mapcat(lambda r: r.discretize(k), recset2)) error1 = max(r.error + shortest_edge(r) for r in recset1) error2 = max(r.error + shortest_edge(r) for r in recset2) error = error1 + error2 d12 = pointwise_hausdorff(xs, ys) yield Interval(max(d12 - error, 0), d12 + error) recset1 = fn.first(filter(lambda xs: -xs[0][0] <= eps, refiner1)) recset2 = fn.first(filter(lambda xs: -xs[0][0] <= eps, refiner2)) recset1, recset2 = [r for _, r in recset1], [r for _, r in recset2] eps /= 2
def staircase_hausdorff(f1, f2, return_expanded=False): def additional_points(i1, i2): '''Minimal distance points between intvl1 and intvl2.''' xs1, xs2 = {i1.start.x, i1.end.x}, {i2.start.x, i2.end.x} ys1, ys2 = {i1.start.y, i1.end.y}, {i2.start.y, i2.end.y} all_points = [ Point2d(x, y) for x, y in fn.chain(product(xs1, ys2), product(xs2, ys1)) ] new_f1 = {p for p in all_points if p in i1} new_f2 = {p for p in all_points if p in i2} return new_f1, new_f2 f1_intervals = [Interval(p1, p2) for p1, p2 in zip(f1, f1[1:])] f2_intervals = [Interval(p1, p2) for p1, p2 in zip(f2, f2[1:])] f1_extras, f2_extras = zip( *(additional_points(i1, i2) for i1, i2 in product(f1_intervals, f2_intervals))) F1 = list(set(f1) | set.union(*f1_extras)) F2 = list(set(f2) | set.union(*f2_extras)) return mdth.pointwise_hausdorff(F1, F2)
def test_staircase_hausdorff(k, xys1, xys2): def discretize(intvl): p1, p2 = intvl xs = np.linspace(p1.x, p2.x, 2 + k) ys = np.linspace(p1.y, p2.y, 2 + k) return [Point2d(x, y) for x, y in product(xs, ys)] f1 = [Point2d(x, y) for x, y in zip(*xys1)] f2 = [Point2d(x, y) for x, y in zip(*xys2)] f1_hat = set(fn.mapcat(discretize, zip(f1, f1[1:]))) f2_hat = set(fn.mapcat(discretize, zip(f2, f2[1:]))) # Check discretization works as expected assert len(f1_hat) == (len(f1) - 1) * k + len(f1) assert len(f2_hat) == (len(f2) - 1) * k + len(f2) # Check extended array has smaller distance d1 = mdth.pointwise_hausdorff(f1_hat, f2_hat) d2 = staircase_hausdorff(f1, f2) event(f"d1, d2={d1, d2}") assert d2 <= d1 or pytest.approx(d1) == d2